gpt4 book ai didi

haskell - 如何绑定(bind)两个 IO () monad 而不执行它们?

转载 作者:行者123 更新时间:2023-12-02 10:12:10 25 4
gpt4 key购买 nike

在下面的代码中,我使用 >> 将 IO 操作连接在一起。但是 AFAIU,m1>>m2 被脱糖为 m1>>=(\_.m2),因此它在绑定(bind)时执行第一个 IO 操作。我希望所有打印都在主体中进行,即打印语句不应与输入语句(“输入代码”)交错。因为 do 不允许我返回除 IO 之外的任何其他 monad,例如 [IO ()]。怎样才能得到想要的打印效果呢?

f :: [Int] -> IO ()
f inventory = do
putStrLn "Enter Code\n"
x <- getLine
let idx = nameToIndex x
putStrLn "Quantity\n"
y <- getLine
putStrLn "More?\n"
c <- getChar
let q = (read y :: Int)
let curM = if inventory !! idx >= q then (putStrLn "sdaf\n") else (putStrLn "Overflow!\n")
if c == 'Y' then curM>>(f (update inventory idx)) else curM

main = f [1, 2]

最佳答案

我不是100%确定我理解这个问题,但我认为它是这样的:你想与用户进行一些交互,存储有关交互的信息,然后一次显示所有信息整个交互结束。

这是代码的一个非常简化的版本,它跳过所有业务逻辑,只是不断询问用户是否要继续。

prompt = do
putStrLn "Continue?"
s <- getLine
case s of
"y" -> putStrLn "Okay, let's continue." >> prompt
_ -> return ()

main = prompt

认为您要求的效果是延迟显示“好吧,让我们继续”。直到用户停止点击“y”。那没问题。有很多方法可以做到这一点。最灵活的是让 prompt 在完成后返回它想要执行的操作:

prompt = do
putStrLn "Continue?"
s <- getLine
case s of
"y" -> do
act <- prompt
return (putStrLn "Okay, let's continue." >> act)
_ -> return (return ())

main = do
act <- prompt
act

(也有组合器可以使代码更加紧凑。)但我不喜欢这种设计;这使得反射(reflection) prompt 的结果变得困难。一种更专业但也更易于维护的方法是返回一些描述交互的数据,然后调用者可以将其转换为总结事物的 IO 操作。在这种情况下,字符串列表似乎是合适的描述。

prompt = do
putStrLn "Continue?"
s <- getLine
case s of
"y" -> do
results <- prompt
return ("Okay, let's continue." : results)
_ -> return []

main = do
results <- prompt
mapM_ putStrLn results

希望这个解释足够清楚,以便您可以将这个想法与更复杂的业务逻辑结合起来。

关于haskell - 如何绑定(bind)两个 IO () monad 而不执行它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47334963/

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