3

我知道您应该将要对结果执行的操作包装在 monad 中,而不是从 monad 中解包。

我找不到任何白痴友好的例子来说明如何做到这一点。

例如,我想做这样的事情:

myFunction = do
    c <- getChar
    if (c == 'q')
        then putStrLn "take action 1"
        else putStrLn "take action 2"

但是您不能直接将 char 文字与 IO Char 进行比较。

GHCi 版本是 8.4.4。

错误信息:

[1 of 2] Compiling Lib              ( /Users/jamesstrieter/hask-tink/src/Lib.hs, interpreted )

/Users/jamesstrieter/hask-tink/src/Lib.hs:66:18: error:
    • Couldn't match expected type ‘IO char’ with actual type ‘Char’
    • In the second argument of ‘(==)’, namely ‘'q'’
      In the expression: x == 'q'
      In an equation for ‘what2do’: what2do x = x == 'q'
    • Relevant bindings include
        x :: IO char
          (bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:9)
        what2do :: IO char -> Bool
          (bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:1)
   |
66 | what2do x = x == 'q'
   |                  ^^^
Failed, no modules loaded.
4

3 回答 3

9

您发布的代码看起来完全正确且功能强大。

do-notation 是在 monad 中处理值的一种方式。

c <- getChar在 do 块内将 c 绑定到IO Char您使用getChar. 您可以c == 'q'在这里进行比较,因为 c 是普通字符,而不是IO Char.

要回答您直接的问题,您可以使用该return函数将纯值放入任何 monad,包括 IO,因此return 'q'将字符文字“q”“包装”到 monad 中。在这种情况下,这不是您想要的,您已经拥有的代码就是您正在寻找的。

于 2019-03-10T04:56:56.770 回答
6

但是您不能直接将 char 文字与 IO Char 进行比较。

当然,但是当您“绑定” IO 操作的结果时,它不再是IO Chara 而只是 aChar所以这就是它起作用的原因。

更多的话:

Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char
于 2019-03-10T04:56:21.600 回答
2

理解 monad 最重要的事情之一IO是表达式m >>= f不执行动作,也不调用函数mf

相反,它只是创建了一个 IO的动作,它包装了mf,当执行时,最终会执行,提取返回值,然后通过使用该值m调用当场计算出的下一个动作。f

而已。您的整个 Haskell 程序只不过是一个 DSL,用于构建分配给 的单个 IO 操作,mainHaskell运行时将为您执行该操作。

所以当你写

-- Rewritten slightly for brevity
myFunction = do
    c <- getChar
    putStrLn (if (c == 'q')
        then "take action 1"
        else "take action 2")

这被取消了

myFunction = getChar >>= (\c -> 
                putStrLn (if (c == 'q') 
                    then "take action 1" 
                    else "take action 2")

你实际上是在说“构建一个IO包含getChar和类型的函数的动作Char -> IO (),这样当执行这个动作时,它会执行getChar并将结果传递Char给函数以产生另一个 IO要立即执行的动作。”

于 2019-03-10T14:36:26.663 回答