gpt4 book ai didi

haskell - 如何连接两个 Haskell IO monad

转载 作者:行者123 更新时间:2023-12-03 22:56:45 25 4
gpt4 key购买 nike

以下(有效的)Haskell 程序输出一个随机拼写:

import System.Random

spells =
[ "Abracadabra!"
, "Hocus pocus!"
, "Simsalabim!"
]

main :: IO()
main = do
spell <- (spells !!) <$> randomRIO (0, length spells - 1)
putStrLn spell

但是,变量spell 是完全没用的。它存储从法术列表中选择的随机字符串,但随后立即传递给 putStrLn 函数并且不再使用。我试图将两个 IO 操作组合成一行,如下所示:

main = putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)

但是我得到了以下错误:

    • Couldn't match type ‘IO ()’ with ‘()’
Expected type: Int -> ()
Actual type: Int -> IO ()
• In the first argument of ‘(<$>)’, namely
‘putStrLn <$> (spells !!)’
In the expression:
putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)
In an equation for ‘main’:
main
= putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)
|
160 | main = putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^

有没有办法把两个IO操作合并成一行?我看了this similar question但我无法理解答案。

最佳答案

(>>=)是 Robin Zigmond 的回答中给出的“规范”monad 运算符。但是,如果您尝试以类似应用程序的风格编写代码,我经常喜欢使用它的翻转版本,(=<<) .它与 Functor 和 Applicative 中的函数有很好的对称性,它们与普通的非 monadic 函数调用非常相似,只是插入了一个额外的运算符:

f x -- one-argument function call
f <$> fx -- fmapping that function into a functor
g x y -- two-argument function call
g <$> ax <*> ay -- applied over two applicatives
f =<< mx -- binding a function with a monadic value
mx >>= f -- looks backwards, doesn't it?

所以你的表达式可以写成

main = putStrLn =<< (spells !!) <$> randomRIO (0, length spells - 1)

就我个人而言,我宁愿使用更多的普通函数组合和更少的上下文映射,所以我会移动 (spells !!)在绑定(bind)运算符的左侧:

main = putStrLn . (spells !!) =<< randomRIO (0, length spells - 1)

看看按这样的顺序读起来怎么样? “打印出 randomRIO (0, length spells - 1) 给出的索引处的拼写”?

关于haskell - 如何连接两个 Haskell IO monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64163071/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com