正确使用符号

nob*_*ody 4 monads haskell

我想了解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

Phi*_* JF 8

问题是你用纯值混淆包裹的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)

也就是说,该函数>>=取:类型的参数ma和的函数从amb并返回mb.

这段代码怎么样?

(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


Dan*_*ner 8

我不同意其他人的意见,并且说你正在做的事几乎肯定与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)