Skip to content

Instantly share code, notes, and snippets.

@gvolpe
Last active November 6, 2018 06:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvolpe/3d554d9821a2ee61c1c79a1fcb984c1b to your computer and use it in GitHub Desktop.
Save gvolpe/3d554d9821a2ee61c1c79a1fcb984c1b to your computer and use it in GitHub Desktop.
Solving this problem using the `polymorphism` library: https://apocalisp.wordpress.com/2010/07/02/higher-rank-polymorphism-in-scala/
import cats.Id
import polymorphic._
import polymorphic.syntax.all._
// Type mismatch: found b.type, required: A
//def nope[A, B](f: A => List[A], b: B, s: String): (List[B], List[String]) = (f(b), f(s))
// If Scala had Rank-N types it would be defined as:
//def notValid[B](f: (A => List[A]) forAll { A }, b: B, s: String): (List[B], List[String]) = (f(b), f(s))
class PolyList[A] {
def f: A => List[A] = a => List(a)
}
def yay[A](fr: ∀[PolyList], a: A, s: String): (List[A], List[String]) = (fr[A].f(a), fr[String].f(s))
yay(∀(new PolyList), 123, "gvolpe") // res1: (List[Int], List[String]) = (List(123),List(gvolpe))
// ---- even better, extend Function1[A, List[A]]
class ForAllFunction1[A] extends (A => List[A]) {
def apply(a: A): List[A] = List(a)
}
def yay2[A](fr: ∀[ForAllFunction1], a: A, s: String): (List[A], List[String]) = (fr[A](a), fr[String](s))
yay2(∀(new ForAllFunction1), 123, "gvolpe") // res2: (List[Int], List[String]) = (List(123),List(gvolpe))
// ----- or as solved in the blog post, using natural transformation:
val singletonList = new (Id ~> List) {
def apply[A](a: A): List[A] = List(a)
}
def yay3[A](f: Id ~> List, a: A, s: String): (List[A], List[String]) = (f[A](a), f[String](s))
yay3(fn(List), 123, "gvolpe") //res3: (List[Int], List[String]) = (List(123),List(gvolpe))
// ----- using natural transformation with `polymorphism` syntax:
def yay4[A](f: Id ~> List, a: A, s: String): (List[A], List[String]) = (f[A](a), f[String](s))
yay4(fn[Id, List](a => List(a)), 123, "gvolpe")
// or just
yay4(fn(a => List(a)), 123, "gvolpe")
{-# LANGUAGE RankNTypes #-}
foo :: (forall a . a -> [a]) -> b -> ([b], [String])
foo f x = (f x, f "foo")
bar :: ([Int], [String])
bar = foo (: []) 123
-- Even more generic
foo' :: (forall a . a -> [a]) -> b -> c -> ([b], [c])
foo' f x y = (f x, f y)
bar' :: ([Int], [String])
bar' = foo' (: []) 123 "gvolpe"
main :: IO ()
main = putStrLn $ show (fst bar) ++ show (snd bar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment