关于函数monad [英] About the function monad
问题描述
我对函数monad有些疑惑。 monad函数定义如下:
$ b $ pre $ instance Monad(( - >)r)其中
return x = \_ - > x
h>> = f = \ w - > f(hw)w
我试图通过编写绑定操作来解决它:
((* 2)>> =(+10))3
(返回3): :(( - >)Int)
但它导致错误。我还尝试将一个AddStuff函数重写到绑定操作中。
addStuff = do
a < - (* 2)
b < - (+10)
return(a + b)
<然后将这个函数转换为
$ $ $ $ $ $ $ $ addStuff'w =(* 2)w>> =(\ a - >
(+10)w>> =(\ b - >
return(a + b)))
$ p
$ b
我检查新函数的类型,参见
addStuff: :(Monad m,Num(mb),Num b)=> m b - > m b
这是为什么?如何解决这个问题?
在 addStuff'
code>(* 2)w 和(+ 10)w
。这些分别相当于 w * 2
和 w + 10
。所以 addStuff'
等价于:
addStuff'w = w * 2>> = \ a - >
w + 10>> = \ b - >
return(a + b)
用这种方式写下来应该很明显,左操作数为>> =
是数字,而不是函数。这就是为什么推断类型告诉你,你的函数只适用于单数的数字。
当消除 do
注释到>> =
的左操作数应该与< -
的右操作数完全相同。同样消除 do
notation不会为该函数添加任何参数。因此,正确的重写将如下所示:
addStuff'=(* 2)>> = \a - > ;
(+10)>> = \ b - >
return(a + b)
至于为什么你以前的代码段不起作用:
((* 2)>> =(+10 ))3
运算符>> =
键入 ma - > (a - > m b) - > m b
。为了简单起见,我们假设这段代码中的所有数字都有类型 Int
,那么你的左操作数的类型为 Int - >如果
m
是( - >),则或
。因此,对于某些类型 m Int
)Int b
,右操作数应该有类型 Int - > (( - >)Int)b
或者更可读地, Int→> Int - > B'/ code>。它实际具有的类型是
Int - > INT
。因此你的表达是不正确的。
(return 3)::(( - >)int)
(( - >)Int)
has kind * - > *
- 值的类型必须是 *
。
这有些不同: return 3
对于某些 m
m Int >(为了简单起见,仍假设所有整数文字都有类型 Int
)。因此,如果 m
是`(( - >)Int)
,则的类型返回3
将是(( - >)Int)Int
或 Int - > Int
,而不是(( - >)Int)
。
I have some confusion with the function monad. The function monad is defined as follow:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
I tried to play around with it by writing a binding operation:
( (*2) >>= (+10) ) 3
(return 3) :: ((->) Int)
But it caused errors. And I also try to rewrite a function AddStuff into the binding operations.
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
then convert this function into
addStuff' w = (*2) w >>= (\a ->
(+10) w >>= (\b ->
return (a+b) ))
I check the type of the new function as see
addStuff :: (Monad m, Num (m b), Num b) => m b -> m b
Why is that? How can I fix that?
In addStuff'
you write (*2) w
and (+10) w
. Those are equivalent to w*2
and w+10
respectively. So addStuff'
is equivalent to this:
addStuff' w = w*2 >>= \a ->
w+10 >>= \b ->
return (a+b)
Writing it this way should make it obvious that here the left operands to >>=
are numbers, not functions. That's why the inferred type is telling you that your function only works for numbers that are monads.
When eliminating do
notation the left operand to >>=
should be exactly the same as the right operand of <-
. Also eliminating do
notation does not add any arguments to the function. So the correct rewriting would look like this:
addStuff' = (*2) >>= \a ->
(+10) >>= \b ->
return (a+b)
As to why your earlier pieces of code don't work:
( (*2) >>= (+10) ) 3
The operator >>=
has type m a -> (a -> m b) -> m b
. For simplicity let's assume that all the numbers in this code have type Int
, then your left operand has type Int -> Int
or m Int
if m
is (->) Int
. So for some type b
the right operand should have type Int -> ((->) Int) b
or, more readably, Int -> Int -> b
. The type it actually has though is Int -> Int
. Therefore your expression is ill-typed.
(return 3) :: ((->) Int)
((->) Int)
has kind * -> *
- the type of a value must have kind *
.
Or to approach this differently: return 3
has type m Int
for some m
(still assuming that all integer literals have type Int
for simplicity). So if m
is `((->) Int)
, the type of return 3
will be ((->) Int) Int
or Int -> Int
, not ((->) Int)
.
这篇关于关于函数monad的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!