如何在 Haskell 的 IO monad 中包装 char 文字?
How to wrap char literal in IO monad in Haskell?
我知道您应该将要对结果执行的操作包装在 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.
But you can't compare a char literal to an IO Char directly.
当然可以,但是当您 "bind" IO 操作的结果时,它不再是 IO Char
,而是 Char
,这就是它起作用的原因。
更多的话:
Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char
您发布的代码看起来完全正确且功能正常。
do-notation 是在 monad 中处理值的一种方式。
do 块中的 c <- getChar
将 c 绑定到 IO Char
中的字符,您使用 getChar
获得。你可以在这里比较 c == 'q'
就好了,因为 c 是一个普通的字符,而不是 IO Char
。
为了直接回答你的问题,你可以使用 return
函数将纯值放入任何 monad,包括 IO,所以 return 'q'
"wraps" 字符文字 'q' 变成一个单子。在这种情况下,这不是您想要的,您已经拥有的代码正是您要寻找的。
关于 IO
monad 最重要的事情之一是表达式 m >>= f
不 执行操作 m
,它也不会调用函数 f
.
相反,它只是创建了一个 new IO
动作来包裹 m
和 f
,which,执行时,最后会执行m
,提取return值,然后用该值调用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")
你实际上是在说“构建一个包含 getChar
的 IO
动作和一个 Char -> IO ()
类型的函数,这样当这个动作被执行时,它会执行 getChar
并将生成的 Char
传递给函数以生成 另一个 IO
立即执行的操作。"
我知道您应该将要对结果执行的操作包装在 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.
But you can't compare a char literal to an IO Char directly.
当然可以,但是当您 "bind" IO 操作的结果时,它不再是 IO Char
,而是 Char
,这就是它起作用的原因。
更多的话:
Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char
您发布的代码看起来完全正确且功能正常。
do-notation 是在 monad 中处理值的一种方式。
do 块中的c <- getChar
将 c 绑定到 IO Char
中的字符,您使用 getChar
获得。你可以在这里比较 c == 'q'
就好了,因为 c 是一个普通的字符,而不是 IO Char
。
为了直接回答你的问题,你可以使用 return
函数将纯值放入任何 monad,包括 IO,所以 return 'q'
"wraps" 字符文字 'q' 变成一个单子。在这种情况下,这不是您想要的,您已经拥有的代码正是您要寻找的。
关于 IO
monad 最重要的事情之一是表达式 m >>= f
不 执行操作 m
,它也不会调用函数 f
.
相反,它只是创建了一个 new IO
动作来包裹 m
和 f
,which,执行时,最后会执行m
,提取return值,然后用该值调用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")
你实际上是在说“构建一个包含 getChar
的 IO
动作和一个 Char -> IO ()
类型的函数,这样当这个动作被执行时,它会执行 getChar
并将生成的 Char
传递给函数以生成 另一个 IO
立即执行的操作。"