Created
July 11, 2012 11:38
-
-
Save imeredith/3089818 to your computer and use it in GitHub Desktop.
This file contains 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
trait PartialType[T[_, _], A] { | |
type Apply[B] = T[A, B] | |
type Flip[B] = T[B, A] | |
} | |
trait Fluffy[F[_]] { | |
def furry[A, B](f: A => B, fa: F[A]): F[B] | |
} | |
object Fluffy { | |
// Exercise 1 | |
// Relative Difficulty: 1 | |
def ListFluffy: Fluffy[List] = new Fluffy[List] { | |
def furry[A, B](f: (A) => B, fa: List[A]): List[B] = fa.map(f) | |
} | |
// Exercise 2 | |
// Relative Difficulty: 1 | |
def OptionFluffy: Fluffy[Option] = new Fluffy[Option] { | |
def furry[A, B](f: (A) => B, fa: Option[A]): Option[B] = fa.map(f) | |
} | |
// Exercise 3 | |
// Relative Difficulty: 1 | |
def StreamFluffy: Fluffy[Stream] = new Fluffy[Stream] { | |
def furry[A, B](f: (A) => B, fa: Stream[A]): Stream[B] = fa.map(f) | |
} | |
// Exercise 5 | |
// Relative Difficulty: 5 | |
def Function1Fluffy[X]: Fluffy[PartialType[Function1, X]#Apply] = new Fluffy[PartialType[Function1, X]#Apply] { | |
def furry[A, B](f: Function1[A, B], fa: Function1[X, A]): Function1[X, B] = f.compose(fa) | |
} | |
// Exercise 6 | |
// Relative Difficulty: 6 | |
def EitherLeftFluffy[X]: Fluffy[PartialType[Either.LeftProjection, X]#Flip] = new Fluffy[PartialType[LeftProjection, X]#Flip] { | |
def furry[A, B](f: (A) => B, fa: LeftProjection[A, X]): LeftProjection[B, X] = LeftProjection(fa.map(f)) | |
} | |
// Exercise 7 | |
// Relative Difficulty: 4 | |
def EitherRightFluffy[X]: Fluffy[PartialType[Either.RightProjection, X]#Apply] = new Fluffy[PartialType[RightProjection, X]#Apply] { | |
def furry[A, B](f: (A) => B, fa: RightProjection[X, A]): RightProjection[X, B] = RightProjection(fa.map(f)) | |
} | |
} | |
trait Misty[M[_]] extends Fluffy[M] { | |
def banana[A, B](f: A => M[B], ma: M[A]): M[B] | |
def unicorn[A](a: A): M[A] | |
// Exercise 8 | |
// Relative Difficulty: 3 | |
// (use banana and/or unicorn) | |
def furry[A, B](f: A => B, ma: M[A]): M[B] = banana((a: A) => unicorn(f(a)), ma) | |
} | |
object Misty { | |
// Exercise 9 | |
// Relative Difficulty: 2 | |
def ListMisty: Misty[List] = new Misty[List] { | |
def banana[A, B](f: (A) => List[B], ma: List[A]): List[B] = ma flatMap f | |
def unicorn[A](a: A): List[A] = List(a) | |
} | |
// Exercise 10 | |
// Relative Difficulty: 2 | |
def OptionMisty: Misty[Option] = new Misty[Option] { | |
def banana[A, B](f: (A) => Option[B], ma: Option[A]): Option[B] = ma flatMap f | |
def unicorn[A](a: A): Option[A] = Option(a) | |
} | |
// Exercise 11 | |
// Relative Difficulty: 2 | |
def StreamMisty: Misty[Stream] = new Misty[Stream] { | |
def banana[A, B](f: (A) => Stream[B], ma: Stream[A]): Stream[B] = ma flatMap f | |
def unicorn[A](a: A): Stream[A] = Stream(a) | |
} | |
// Exercise 13 | |
// Relative Difficulty: 6 | |
def Function1Misty[X]: Misty[PartialType[Function1, X]#Apply] = new Misty[PartialType[Function1, X]#Apply] { | |
def banana[A, B](f: (A) => (X) => B, ma: (X) => A): (X) => B = (x: X) => f(ma(x))(x) | |
def unicorn[A](a: A): (X) => A = (_) => a | |
} | |
// Exercise 14 | |
// Relative Difficulty: 7 | |
def EitherLeftMisty[X]: Misty[PartialType[Either.LeftProjection, X]#Flip] = new Misty[PartialType[LeftProjection, X]#Flip] { | |
def banana[A, B](f: (A) => LeftProjection[B, X], ma: LeftProjection[A, X]): LeftProjection[B,X]= LeftProjection(ma.flatMap{ a => f(a).e}) | |
def unicorn[A](a: A): PartialType[LeftProjection, X]#Flip[A] = Left[A,X](a).left | |
} | |
// Exercise 15 | |
// Relative Difficulty: 5 | |
def EitherRightMisty[X]: Misty[PartialType[Either.RightProjection, X]#Apply] = new Misty[PartialType[RightProjection, X]#Apply] { | |
def banana[A, B](f: (A) => PartialType[RightProjection, X]#Apply[B], ma: PartialType[RightProjection, X]#Apply[A]): PartialType[RightProjection, X]#Apply[B] = | |
RightProjection(ma.flatMap{ a => f(a).e}) | |
def unicorn[A](a: A): PartialType[RightProjection, X]#Apply[A] = Right[X, A](a).right | |
} | |
// Exercise 16 | |
// Relative Difficulty: 3 | |
def jellybean[M[_], A](ma: M[M[A]], m: Misty[M]): M[A] = m.banana((a: M[A]) => a, ma) | |
// Exercise 17 | |
// Relative Difficulty: 6 | |
def apple[M[_], A, B](ma: M[A], mf: M[A => B], m: Misty[M]): M[B] = m.banana((a: A) => m.banana((b: A=>B) => m.unicorn(b(a)), mf), ma) | |
// Exercise 18 | |
// Relative Difficulty: 6 | |
def moppy[M[_], A, B](as: List[A], f: A => M[B], m: Misty[M]): M[List[B]] = as.foldLeft(m.unicorn(List[B]())) { | |
(mb,a) => m.banana((c:B) => m.banana((d: List[B]) => m.unicorn(d ++ List(c)), mb),f(a)) | |
} | |
} | |
object AdvancedFun { | |
case class State[S, A](f: S => (S, A)) | |
// Exercise 19 | |
// Relative Difficulty: 9 | |
def StateFluffy[S]: Fluffy[PartialType[State, S]#Apply] = new Fluffy[PartialType[State, S]#Apply] { | |
def furry[A, B](f: (A) => B, fa: PartialType[State, S]#Apply[A]): PartialType[State, S]#Apply[B] = State((s:S) => fa.f(s) match {case (a,b) => (a, f(b))}) | |
} | |
// Exercise 20 | |
// Relative Difficulty: 10 | |
def StateMisty[S]: Misty[PartialType[State, S]#Apply] = new Misty[PartialType[State, S]#Apply] { | |
def banana[A, B](f: (A) => PartialType[State, S]#Apply[B], ma: PartialType[State, S]#Apply[A]): PartialType[State, S]#Apply[B] = | |
State((st: S) => ma.f(st) match {case (s,a) => f(a).f(s)}) | |
def unicorn[A](a: A): PartialType[State, S]#Apply[A] = State((s: S) => (s,a)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment