λ Tony's Blog λ
Monad Laws using Reductio (Scala)
Posted on June 26, 2008In the spirit of yesterday’s post that denoted the Functor Laws using Reductio, I will also give the Monad Laws. Before I do however, here is an example use of the FunctorLaws
object that runs 600 unit tests when testing a Functor
implementation for scala.Option[A]
, scala.List
and finally, for the scala.Either[A, _]
functor just to make it a bit quirky and probably confuse a few of you (in that case, ignore it for now!) :)
val prop_OptionIdentity = identity[Option, Int]
val prop_OptionComposition = composition[Option, Int, String, Long]
val prop_ListIdentity = identity[List, Int]
val prop_ListComposition = composition[List, Int, String, Long]
val prop_EitherIdentity = identity[Apply1Of2[Either, String]#Apply, Int]
val prop_EitherComposition = composition[Apply1Of2[Either, String]#Apply, Int, String, Long]
// OK passed 100 tests. (appears 6 times -- once per property)
…and the obligatory Monad Laws follow (import statements omitted this time, but they are the same as previous)…
object MonadLaws {
def leftIdentity[M[_], A, B](implicit m: Monad[M],
am: Arbitrary[M[B]],
aa: Arbitrary[A],
ca: Coarbitrary[A]) =prop((a: A, f: A => M[B]) =>
bind(f, m.unit(a)) === f(a))
m.
def rightIdentity[M[_], A](implicit m: Monad[M],
am: Arbitrary[M[A]]) =prop((ma: M[A]) => m.bind((a: A) =>
unit(a), ma) === ma)
m.
def associativity[M[_], A, B, C](implicit m: Monad[M],
am: Arbitrary[M[A]],
ca: Coarbitrary[A],
cb: Coarbitrary[B],
amb: Arbitrary[M[B]],
amc: Arbitrary[M[C]]) =prop((ma: M[A], f: A => M[B], g: B => M[C]) =>
bind(g, m.bind(f, ma)) === m.bind((a: A) => m.bind(g, f(a)), ma))
m. }
Woot! Woot!