Monad's left unit law does not seem to hold for Lists in scala. Are scala Lists not monads then?

偶尔善良 提交于 2019-12-04 14:12:14

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!