Skip to content
Snippets Groups Projects
Commit fc706444 authored by crater2150's avatar crater2150
Browse files

Rename function "unit" to "pure"

This is consistent with Cats. Also less confusing, as the "unit" method
has nothing to do with the "Unit" type.
parent f6176040
No related branches found
No related tags found
No related merge requests found
Showing
with 34 additions and 34 deletions
......@@ -3,26 +3,26 @@ package applicative
import scala.language.higherKinds
trait Applicative[F[_]] {
def unit[A](a: A): F[A]
def pure[A](a: A): F[A]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = map2(ff, fa)((f, a) => f(a))
// implement map using unit and ap, but not flatMap/flatten
// implement map using pure and ap, but not flatMap/flatten
def map[A, B](fa: F[A])(f: A => B): F[B] = ???
// implement map2 using unit and ap
// implement map2 using pure and ap
// hint: f.curried converts `(A,B) => C` to `A => (B => C)`
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ???
// implement unit first
// implement pure first
// then write the signature for ap and map2
// then implement one of them
def compose[G[_]](implicit G: Applicative[G]): Applicative[Lambda[a => F[G[a]]]] = {
val F = this
new Applicative[Lambda[a => F[G[a]]]] {
def unit[A](a: A): F[G[A]] = ???
def pure[A](a: A): F[G[A]] = ???
//note: when you are done implementing this, the test for ap/map2 will result in a StackOverflow until you implement one of them
......
......@@ -6,6 +6,6 @@ trait Monad[F[_]] extends Applicative[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] = flatten(map(fa)(f))
def flatten[A](fa: F[F[A]]): F[A] = flatMap(fa)(identity)
override def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(f andThen unit)
override def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(f andThen pure)
override def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = flatMap(fa)(a => map(fb)(b => f(a,b)))
}
......@@ -6,7 +6,7 @@ case class Invalid[+E](head: E, tail: List[E] = List()) extends Validated[E, Not
object Validated {
implicit def validatedApplicative[E]: Applicative[Validated[E, +?]] = new Applicative[Validated[E,+?]] {
def unit[A](a: A) = Valid(a)
def pure[A](a: A) = Valid(a)
// add map2 or ap here
}
}
......@@ -2,7 +2,7 @@ package monads
import scala.language.higherKinds
trait Monad[F[_]] {
def unit[A](a: A): F[A]
def pure[A](a: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ???
......
......@@ -4,7 +4,7 @@ final case class Id[A](value: A)
object Id {
// No tests. If it compiles, it's correct.
implicit val idMonad = new Monad[Id] {
def unit[A](a: A): Id[A] = ???
def pure[A](a: A): Id[A] = ???
def flatMap[A, B](fa: Id[A])(f: A => Id[B]): Id[B] = ???
}
}
......@@ -11,7 +11,7 @@ trait Parser[+A] {
object Parser {
implicit val parserMonad: Monad[Parser] = new Monad[Parser] {
def unit[A](a: A): Parser[A] = success(a)
def pure[A](a: A): Parser[A] = success(a)
def flatMap[A, B](fa: Parser[A])(f: A => Parser[B]): Parser[B] =
input => fa.parse(input) match {
......
......@@ -49,7 +49,7 @@ object Parsers extends Parsers {
a <- p
tail <- many(p)
} yield a :: tail
) | Monad[Parser].unit(Nil)
) | Monad[Parser].pure(Nil)
def manyN[A](p: Parser[A], n: Int): Parser[List[A]] =
implicitly[Traverse[List]].sequence(List.fill(n)(p))
......
......@@ -3,7 +3,7 @@ package parsers.lib
object Id {
type Id[A] = A
implicit val idMonad: Monad[Id] = new Monad[Id] {
override def unit[A](a:A): Id[A] = a
override def pure[A](a:A): Id[A] = a
override def flatMap[A,B](a:Id[A])(f: A => Id[B]): Id[B] = f(a)
}
}
......@@ -17,10 +17,10 @@ object Functor {
}
trait Applicative[F[_]] extends Functor[F] {
def unit[A](a: A): F[A]
def pure[A](a: A): F[A]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = map2(ff, fa)((f, a) => f(a))
def map[A, B](fa: F[A])(f: A => B): F[B] = ap(unit(f))(fa)
def map[A, B](fa: F[A])(f: A => B): F[B] = ap(pure(f))(fa)
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ap(map(fa)(a => (b:B) => f(a,b)))(fb)
}
......@@ -32,7 +32,7 @@ trait Monad[F[_]] extends Applicative[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
def flatten[A](fa: F[F[A]]): F[A] = flatMap(fa)(identity)
override def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(f andThen unit)
override def map[A, B](fa: F[A])(f: A => B): F[B] = flatMap(fa)(f andThen pure)
override def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = flatMap(fa)(a => map(fb)(b => f(a,b)))
}
......@@ -61,7 +61,7 @@ object Traverse {
implicit val listTraverse: Traverse[List] = new Traverse[List] {
override def traverse[G[_], A, B](fa: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
fa.foldRight(G.unit(List[B]()))((a, b) => G.map2(f(a), b)(_ :: _))
fa.foldRight(G.pure(List[B]()))((a, b) => G.map2(f(a), b)(_ :: _))
}
}
......@@ -12,7 +12,7 @@ object Reader {
val a = fa.run(in)
f(a).run(in)
})
override def unit[A](a: A): Reader[R, A] = Reader(_ => a)
override def pure[A](a: A): Reader[R, A] = Reader(_ => a)
override def map2[A, B, C](fa: Reader[R, A], fb: Reader[R, B])(f: (A, B) => C): Reader[R, C] = Reader(in => {
val a = fa.run(in)
val b = fb.run(in)
......
......@@ -9,7 +9,7 @@ case class State[S, A] private (run: S => (S, A))
case object State {
implicit def stateMonad[S]: Monad[State[S, ?]] = new Monad[State[S, ?]] {
override def unit[A](a: A): State[S, A] = State(s => (s, a))
override def pure[A](a: A): State[S, A] = State(s => (s, a))
override def flatMap[A, B](fa: State[S, A])(f: A => State[S, B]): State[S, B] = State(s => {
val (s1, a) = fa.run(s)
f(a).run(s1)
......
......@@ -19,7 +19,7 @@ object Writer {
Writer((implicitly[Monoid[L]].op(fa.v._1, next.v._1), next.v._2))
}
def unit[A](a: A): Writer[L, A] = Writer((implicitly[Monoid[L]].zero, a))
def pure[A](a: A): Writer[L, A] = Writer((implicitly[Monoid[L]].zero, a))
override def map2[A, B, C](fa: Writer[L, A], fb: Writer[L, B])(f: (A, B) => C): Writer[L, C] =
Writer((implicitly[Monoid[L]].op(fa.v._1, fb.v._1), f(fa.v._2, fb.v._2)))
override def map[A, B](fa: Writer[L, A])(f: A => B): Writer[L, B] = Writer((fa.v._1, f(fa.v._2)))
......
......@@ -25,15 +25,15 @@ object Fuse {
def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] =
map2(fab, fa)(_(_))
def unit[A](a: => A): F[A]
def pure[A](a: => A): F[A]
def map[A,B](fa: F[A])(f: A => B): F[B] =
apply(unit(f))(fa)
apply(pure(f))(fa)
def product[G[_]](G: Applicative[G]): Applicative[Lambda[x => (F[x], G[x])]] = {
val self = this
new Applicative[Lambda[x => (F[x], G[x])]]{
def unit[A](a: => A) = (self.unit(a), G.unit(a))
def pure[A](a: => A) = (self.pure(a), G.pure(a))
override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) =
(self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
}
......
......@@ -4,25 +4,25 @@ object SequenceMap {
def sequenceMap[K,V](m: Map[K, F[V]]): F[Map[K,V]] = ???
//you can use any of these methods
def unit[A](a: => A): F[A]
def pure[A](a: => A): F[A]
def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)((ab, a) => ab(a))
def map[A,B](fa: F[A])(f: A => B): F[B] = apply(unit(f))(fa)
def map[A,B](fa: F[A])(f: A => B): F[B] = apply(pure(f))(fa)
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
apply(apply(unit(f.curried))(fa))(fb)
apply(apply(pure(f.curried))(fa))(fb)
def map3[A,B,C,D](fa: F[A], fb: F[B], fc: F[C])(f: (A, B, C) => D): F[D] =
apply(apply(apply(unit(f.curried))(fa))(fb))(fc)
apply(apply(apply(pure(f.curried))(fa))(fb))(fc)
def factor[A,B](fa: F[A], fb: F[B]): F[(A,B)] =
map2(fa, fb)((_,_))
def sequence[A](fas: List[F[A]]): F[List[A]] =
fas.foldRight[F[List[A]]](unit(Nil))((a, b) => map2(a, b)(_::_))
fas.foldRight[F[List[A]]](pure(Nil))((a, b) => map2(a, b)(_::_))
def traverse[A,B](fas: List[A])(f: A => F[B]): F[List[B]] =
fas.foldRight[F[List[B]]](unit(Nil))((a, b) => map2(f(a), b)(_::_))
fas.foldRight[F[List[B]]](pure(Nil))((a, b) => map2(f(a), b)(_::_))
}
}
......@@ -5,11 +5,11 @@ import testutil.PendingIfUnimplemented
class ApplicativeSpec extends FlatSpec with Matchers with AppendedClues with PendingIfUnimplemented {
implicit val optionApplicative = new Applicative[Option] {
override def unit[A](a: A): Option[A] = Some(a)
override def pure[A](a: A): Option[A] = Some(a)
override def ap[A, B](ff: Option[A => B])(fa: Option[A]): Option[B] = ff.flatMap(f => fa.map(f))
}
implicit val listApplicative = new Applicative[List] {
override def unit[A](a: A): List[A] = List(a)
override def pure[A](a: A): List[A] = List(a)
override def ap[A, B](ff: List[A => B])(fa: List[A]): List[B] = ff.flatMap(f => fa.map(f))
}
......@@ -33,10 +33,10 @@ class ApplicativeSpec extends FlatSpec with Matchers with AppendedClues with Pen
optionApplicative.map2(Some(2), Option.empty[Int])((a, b) => a + b) shouldBe None
}
"compose" should "create nested element with unit" in {
"compose" should "create nested element with pure" in {
val ola: Applicative[Lambda[a => Option[List[a]]]] = optionApplicative.compose(listApplicative)
ola.unit(5) shouldBe Some(List(5))
ola.pure(5) shouldBe Some(List(5))
}
it should "implement map2 or ap correctly" in {
......
......@@ -6,7 +6,7 @@ import testutil.PendingIfUnimplemented
class MonadFunctorSpec extends FlatSpec with Matchers with AppendedClues with PendingIfUnimplemented {
"functorFromMonad" should "return a working functor" in {
Functor.functorFromMonad[Option](new Monad[Option] {
def unit[A](a: A): Option[A] = Some(a)
def pure[A](a: A): Option[A] = Some(a)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] =
fa.flatMap(f)
}).map[Int, String](Some(3))(_.toString) shouldBe Some("3")
......
......@@ -24,7 +24,7 @@ class MonadSpec extends FlatSpec with Matchers with AppendedClues with PendingIf
}
val tupleMonad = new Monad[Tuple1] {
def unit[A](a: A): Tuple1[A] = Tuple1(a)
def pure[A](a: A): Tuple1[A] = Tuple1(a)
def flatMap[A, B](fa: Tuple1[A])(f: A => Tuple1[B]): Tuple1[B] =
f(fa._1)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment