我对monad函数有些困惑。函数monad的定义如下:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
我试图通过编写绑定操作来解决它:
( (*2) >>= (+10) ) 3
(return 3) :: ((->) Int)
但是它导致了错误。而且我还尝试将函数AddStuff重写为绑定操作。
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
然后将该函数转换为
addStuff' w = (*2) w >>= (\a ->
(+10) w >>= (\b ->
return (a+b) ))
我检查新函数的类型,请参见
addStuff :: (Monad m, Num (m b), Num b) => m b -> m b
为什么?我该如何解决?
在addStuff'
中,您写入(*2) w
和(+10) w
。它们分别等效于w*2
和w+10
。因此,addStuff'
等效于此:
addStuff' w = w*2 >>= \a ->
w+10 >>= \b ->
return (a+b)
以这种方式编写的代码应该很明显,这里>>=
的左操作数是数字,而不是函数。这就是为什么推断类型告诉您您的函数仅适用于单子数字的原因。
[消除do
表示法时,>>=
的左操作数应与<-
的右操作数完全相同。同样消除do
表示法不会向该函数添加任何参数。因此正确的重写应如下所示:
addStuff' = (*2) >>= \a ->
(+10) >>= \b ->
return (a+b)
关于您的早期代码为何无效的原因:
( (*2) >>= (+10) ) 3
运算符>>=
的类型为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)
[((->) Int)
具有种类* -> *
-值的类型必须具有种类*
。
或采取不同的方法:return 3
对于某些m Int
具有类型m
(为简单起见,仍假定所有整数文字都具有Int
类型)。因此,如果m
为((->) Int)
,则return 3
的类型将为((->) Int) Int
或Int -> Int
,而不是((->) Int)
。