Last active
August 29, 2015 14:18
-
-
Save milessabin/63de4353d43721c93677 to your computer and use it in GitHub Desktop.
Function type inference not too shabby ...
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 ops.function._ | |
// Contravariant version of shapeless's FnToProduct | |
trait ContraFnToProduct[-F] { | |
type Out | |
def apply(f: F): Out | |
} | |
object ContraFnToProduct { | |
type Aux[F, Out0] = ContraFnToProduct[F] { type Out = Out0 } | |
implicit def fnp2[A, B, C, Res]: Aux[(A, B, C) => Res, (A :: B :: C :: HNil) => Res] = | |
new ContraFnToProduct[(A, B, C) => Res] { | |
type Out = (A :: B :: C :: HNil) => Res | |
def apply(f: (A, B, C) => Res): Out = (l: A :: B :: C :: HNil) => f(l.head, l.tail.head, l.tail.tail.head) | |
} | |
} | |
object Test extends App { | |
class HListSyntax[A <: HList, F <: AnyRef](a: A) { | |
def $$[U](f: F)(implicit cftp: ContraFnToProduct.Aux[f.type, A => U]): U = cftp(f)(a) | |
} | |
implicit def mkSyntax[A <: HList, F <: AnyRef](a: A) | |
(implicit ffp: FnFromProduct.Aux[A => Any, F]): HListSyntax[A, F] = | |
new HListSyntax[A, F](a) | |
implicit def mkSyntax[P, A <: HList, F <: AnyRef](p: P) | |
(implicit gen: Generic.Aux[P, A], ffp: FnFromProduct.Aux[A => Any, F]): HListSyntax[A, F] = | |
new HListSyntax[A, F](gen.to(p)) | |
val res0 = (2 :: "a" :: 1.3 :: HNil) $$ ((i, s, d) => (s * i, d * i)) // Function argument types inferred | |
assert((res0: (String, Double)) == ("aa", 2.6)) | |
// Tuples | |
val res1 = (2, "a", 1.3) $$ ((i, s, d) => (s * i, d * i)) // Function argument types inferred | |
assert((res1: (String, Double)) == ("aa", 2.6)) | |
// Types (eg. case classes) with a Generic instance | |
case class Foo(i: Int, s: String, d: Double) | |
val res2 = Foo(2, "a", 1.3) $$ ((i, s, d) => (s * i, d * i)) // Function argument types inferred | |
assert((res2: (String, Double)) == ("aa", 2.6)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment