Created
May 9, 2019 06:50
-
-
Save monadplus/88d7c73e1c81e12aee1f856312fa78b4 to your computer and use it in GitHub Desktop.
Last element of a product
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shapeless._ | |
import scala.annotation.implicitNotFound | |
trait DeepFn1[T] { | |
type Out | |
def apply(t: T): Out | |
} | |
@implicitNotFound("Implicit not found: Last[${L}]. ${L} is empty, so there is no last element.") | |
trait Last[L] extends DeepFn1[L] | |
object Last extends LastSyntax { | |
def apply[L](implicit last: Last[L]): Aux[L, last.Out] = last | |
type Aux[L, Out0] = Last[L] {type Out = Out0} | |
implicit def hsingleLast[H]: Aux[H :: HNil, H] = | |
new Last[H :: HNil] { | |
type Out = H | |
def apply(h: H :: HNil): Out = h.head | |
} | |
implicit def hlistLast[H, T <: HList, OutT] | |
(implicit last: Last.Aux[T, OutT]): Aux[H :: T, OutT] = | |
new Last[H :: T] { | |
type Out = OutT | |
def apply(hlist: H :: T): Out = last(hlist.tail) | |
} | |
implicit def genericLast[In, Gen, OutT] | |
(implicit gen: Generic.Aux[In, Gen], | |
last: Last.Aux[Gen, OutT]): Last.Aux[In, OutT] = | |
new Last[In] { | |
type Out = OutT | |
def apply(in: In): OutT = | |
last(gen.to(in)) | |
} | |
} | |
trait LastSyntax { | |
implicit def toLastOps[A](a: A)(implicit ev: Last[A]): LastOps[A, ev.Out] = | |
new LastOps[A, ev.Out] { | |
def last: ev.Out = ev(a) | |
} | |
sealed trait LastOps[A, Out] { | |
def last: Out | |
} | |
} | |
import Last._ | |
case class Person(name: String, age: Int) | |
val john = Person("John", 25) | |
val age: Int = john.last // 25 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment