我对monad函数有些困惑.函数monad定义如下:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
Run Code Online (Sandbox Code Playgroud)
我尝试通过编写绑定操作来解决它:
( (*2) >>= (+10) ) 3
(return 3) :: ((->) Int)
Run Code Online (Sandbox Code Playgroud)
但它造成了错误.我还尝试将函数AddStuff重写为绑定操作.
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
Run Code Online (Sandbox Code Playgroud)
然后将此函数转换为
addStuff' w = (*2) w >>= (\a ->
(+10) w >>= (\b ->
return (a+b) ))
Run Code Online (Sandbox Code Playgroud)
我查看了新功能的类型
addStuff :: (Monad m, Num (m b), Num b) => m b -> m b
Run Code Online (Sandbox Code Playgroud)
这是为什么?我该如何解决这个问题?
sep*_*p2k 17
在addStuff'你写(*2) w和(+10) w.这些分别相当于w*2和w+10.所以addStuff'相当于:
addStuff' w = w*2 >>= \a ->
w+10 >>= \b ->
return (a+b)
Run Code Online (Sandbox Code Playgroud)
以这种方式编写应该很明显,左边的操作数>>=是数字,而不是函数.这就是为什么推断类型告诉你,你的函数只适用于monad的数字.
当消除do表示法时,左操作数>>=应该与右操作数完全相同<-.同时消除do表示法不会向函数添加任何参数.所以正确的重写看起来像这样:
addStuff' = (*2) >>= \a ->
(+10) >>= \b ->
return (a+b)
Run Code Online (Sandbox Code Playgroud)
至于为什么你的早期代码不起作用:
( (*2) >>= (+10) ) 3
Run Code Online (Sandbox Code Playgroud)
操作员>>=有类型m a -> (a -> m b) -> m b.为简单起见,我们假设,在该代码的所有数字有型Int,那么你的左操作数的类型Int -> Int或m Int如果m是(->) Int.因此对于某些类型b,右操作数应该具有类型,Int -> ((->) Int) b或者更可读Int -> Int -> b.它实际上具有的类型是Int -> Int.因此你的表达是错误的.
(return 3) :: ((->) Int)
Run Code Online (Sandbox Code Playgroud)
((->) Int)善良* -> *- 价值的类型必须有种类*.
或以不同的方式接近这一点:return 3已经输入m Int了一些m(仍然假设所有整数文字具有类型Int为简单起见).所以,如果m是`((->) Int),那return 3将是((->) Int) Int或Int -> Int不是((->) Int).
| 归档时间: |
|
| 查看次数: |
4696 次 |
| 最近记录: |