我想了解Monad,我有以下代码
f a b c d =
do one <- a + b
two <- c * d
three <- one + two
return three
Run Code Online (Sandbox Code Playgroud)
以上编译
但是当我得到一个错误
*Main> f 1 2 3 4
:1:1:
No instances for (Num (a0 -> t0), Monad ((->) a0), Monad ((->) t0))
arising from a use of `f'
Possible fix:
add instance declarations for
(Num (a0 -> t0), Monad ((->) a0), Monad ((->) t0))
In the expression: f 1 2 3 4
In an equation for `it': it = f 1 2 3 4
:1:9:
No instance for (Num (a0 -> a0 -> t0))
arising from the literal `4'
Possible fix:
add an instance declaration for (Num (a0 -> a0 -> t0))
In the fourth argument of `f', namely `4'
In the expression: f 1 2 3 4
In an equation for `it': it = f 1 2 3 4
如果我知道为什么上面的代码不起作用,我想我会更接近理解Monad
f 1 2 3 4
问题是你用纯值混淆包裹的monadic值.
首先要知道的是,符号是常规函数调用的语法糖(>>=和>>).因此,看看你的代码也会有所帮助.
让我们尝试更简单的事情
f a b =
do one <- a + b
return one
Run Code Online (Sandbox Code Playgroud)
这与您的代码有同样的问题,但更简单.要理解为什么它不起作用,我们会问:这实际意味着什么?好吧,我们可以<-使用重写符号>>=
f a b = (a + b) >>= \x -> return x
Run Code Online (Sandbox Code Playgroud)
(这不是最简单的表示,但明确指出)
如果您在GHCi中测试以下内容
>> :t (>>=)
Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
也就是说,该函数>>=取:类型的参数m的a和的函数从a到m的b并返回m的b.
这段代码怎么样?
(a + b)
Run Code Online (Sandbox Code Playgroud)
将成为一个数字.另一半怎么样?
\x -> return x
Run Code Online (Sandbox Code Playgroud)
获取类型的对象a并返回m a任何类型的对象a
所以,你需要一个数字,这也是某种东西.你能想到这样的事吗?目前尚不清楚这将是什么,这是一个怀疑这应该打字的理由.
与monad达成协议的一个好方法是查看一些具体的例子.
该Maybe单子表达的可能失败的计算
instance Monad Maybe where
return = Just
(>>=) (Just a) f = f a
(>>=) Nothing _ = Nothing
Run Code Online (Sandbox Code Playgroud)
这可以让你用啪啪的样子说出来
f args = do x <- functionThatMightFail args
y <- anotherfunctionThatMightFail x
return y
Run Code Online (Sandbox Code Playgroud)
或更简单的相同代码
f args = do x <- functionThatMightFail args
anotherfunctionThatMightFail x
Run Code Online (Sandbox Code Playgroud)
也许
f args = functionThatMightFail args >>= anotherfunctionThatMightFail
Run Code Online (Sandbox Code Playgroud)
另一方面,Listmonad捕获了对列表的每个元素执行相同功能的想法,然后将结果连接在一起.简单的例子比比皆是:
f = do x <- [1,2,3,4]
[1..x]
Run Code Online (Sandbox Code Playgroud)
如果您了解这些,请与Statemonad一起玩.它可以帮助您更全面地了解"monad是计算模型".然后我会检查Parsec,当然还有IO
我不同意其他人的意见,并且说你正在做的事几乎肯定与monad无关.您可能只想使用这样一些无聊的旧代码:
f a b c d = three where
one = a + b
two = c * d
three = one + two
Run Code Online (Sandbox Code Playgroud)
或者更简洁:
f a b c d = a + b + c * d
Run Code Online (Sandbox Code Playgroud)