nsf*_*n55 4 monads functional-programming scala
我在scala上阅读James Iry关于Monads 的博客文章.我在第三部分,我对他关于单位的monad第二定律的描述感到困惑.特别是这个说法:
unit(x) flatMap f = f(x)
Run Code Online (Sandbox Code Playgroud)
当我应用我的心理例子,这是jame之前的monadic类型的例子,这似乎永远不会成功
val x = 1
val f = (_:Int) * 2
f(x) == 2 //true
List(x) flatMap f == 2 //fail
Some(x) flatMap f == 2 //fail
Run Code Online (Sandbox Code Playgroud)
事实上,由于类型问题,它们甚至无法编译.
澄清我明白为什么这些都失败了.我理解如何修复它们以便编译.
我的困惑是,这些似乎与文章中提出的理论相冲突.我缺少一步吗?这些类型不是真正的monad吗?标题为"Monads第二定律:单位"的部分是否不正确?
Scala flatMap
需要一个返回集合的函数,而不是一个返回单个元素的函数,就像你的函数一样f
.
使用map
:
List(x) map f
Run Code Online (Sandbox Code Playgroud)
或让你的函数返回一个集合:
val f = (x: Int) => List(x * 2)
List(x) flatMap f
Run Code Online (Sandbox Code Playgroud)
请注意,它也将返回一个集合,而不是一个整数(你会得到List(2)
,而不仅仅是2
).
由于类型问题它不能编译的事实应该告诉你一些事情:f
不是monad法适用的那种函数!
flatMap
当被视为一元操作而不是收集操作时,它采用"一元价值"和从普通价值到一元价值的函数.您的f
函数是从普通值到普通值的函数.
传递f
到flatMap
不破一元法律,它只是不意味着任何东西.这是一个无效的表达.同样1 + "fork" - 1
不违反算术规律1 + x - 1 = x
; 从这个定律我们可以得出结论,1 + "fork" - 1
应该等于"fork",而实际上它是一个编译器错误.那将是一个愚蠢的结论; 法律只是谈论类型正确的事情.