【问题标题】:How to wrap char literal in IO monad in Haskell?如何在 Haskell 的 IO monad 中包装字符文字?
【发布时间】:2019-07-31 17:44:12
【问题描述】:

我知道您应该将要对结果执行的操作封装在 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.

【问题讨论】:

  • 错误信息是什么?这段代码看起来不错。
  • 你不能直接将 char 文字与 IO Char 进行比较 Apparently the code isn't doing that
  • 向问题添加错误消息
  • 您的错误消息似乎与您发布的代码完全不同。请在您的问题中提供代码来说明您的实际问题。
  • 这很好。错误代码是针对一个相关但不同的问题,因此我将为此创建一个单独的问题。抱歉,我是新手。

标签: haskell monads io-monad do-notation


【解决方案1】:

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

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

do 块中的c &lt;- getChar 将c 绑定到IO Char 中的字符,您使用getChar 获得。你可以在这里比较 c == 'q' 就好了,因为 c 是一个普通的字符,而不是 IO Char

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

【讨论】:

  • 只是一个挑剔,getChar 不“返回IO Char,它 IO Char
【解决方案2】:

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

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

更多的话:

Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char

【讨论】:

    【解决方案3】:

    了解IO monad 最重要的一点是表达式m &gt;&gt;= f执行动作m,也不调用函数f .

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

    就是这样。您的整个 Haskell 程序只不过是一个 DSL,用于构建分配给 main 的单个 IO 操作,Haskell runtime 将为您执行该操作。

    所以当你写的时候

    -- 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")
    

    您实际上是在说“构建一个包含getCharChar -&gt; IO () 类型的函数的IO 操作,这样当执行此操作时,它会执行getChar 并传递结果Char到函数以产生 另一个 IO 立即执行的动作。"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 2012-06-29
      • 2016-08-12
      • 1970-01-01
      • 2017-04-27
      • 2011-10-01
      • 1970-01-01
      相关资源
      最近更新 更多