问题
Monads' "left unit law":
unit(x) flatMap f == f(x)
But:
(List(1) flatMap ((x: Int) => Some[Int](x))) == List(1) // true
((x: Int) => Some[Int](x))(1) == Some(1) // also true
So left unit law does not hold for lists in scala. Are lists not monads then?
回答1:
First, the monad law assumes f: A => M[A]
(here f: A => List[A]
). This is not true of (x: Int) => Some[Int](x)
.
Second, List
's flatMap
is not monadic bind. It is more general than bind, because it takes an implicit CanBuildFrom
that allows it to change its return type depending on what you want it to return. You can restrict it to bind like so
def bind[A](xs: List[A])(f: A => List[A]) = xs.flatMap(f) // implicit (List.canBuildFrom)
Now you can see that the law is satisfied:
bind(List(1))(x => List(x, x)) == List(1, 1)
回答2:
I'm not a category theory or Haskell expert but I don't understand your question, and my response is too big for comment, not to mention code blocks look terrible in comment.
Haskell left identity law is return a >>= f ≡ f a
, right?
In Scala:
return -> apply
>>= -> flatMap
So, left identity law for Scala List
would be List(a).flatMap(f) = f(a)
In your case, val a = 1
and val f = (x: Int) => Some[Int](x)
. But this wouldn't even compile because Option
is not a GenTraversableOnce
; you can't return Option
from a List.flatMap
.
Instead, if we define val f = (x: Int) => List(x * 2)
, a double function
LHS: List(a).flatMap(f) = List(2)
RHS: f(a) = List(2)
LHS = RHS, left identity satisfied.
Am I missing something?
来源:https://stackoverflow.com/questions/45002864/monads-left-unit-law-does-not-seem-to-hold-for-lists-in-scala-are-scala-lists