gpt4 book ai didi

haskell - 是否建议以尾递归形式使用递归IO操作?

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

考虑以下两种变化:

myReadListTailRecursive :: IO [String]
myReadListTailRecursive = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}

myReadListOrdinary :: IO [String]
myReadListOrdinary = do
inp <- getLine
if inp == "" then
return []
else
do
moreInps <- myReadListOrdinary
return (inp:moreInps)

在普通的编程语言中,人们会知道尾递归变体是更好的选择。

但是,通过this answer ,显然haskell对递归的实现与重复使用递归栈的实现并不相似。

但是因为在这种情况下,所讨论的程序涉及操作和严格的单子(monad),所以我不确定相同的推理是否适用。事实上,我认为在IO情况下,尾递归形式确实更好。我不知道如何正确地推理这一点。

<小时/>

编辑:David Young 指出,这里最外层的调用是 (>>=)。即使在这种情况下,其中一种风格是否比另一种更有优势?

最佳答案

FWIW,我会选择现有的单子(monad)组合器并专注于可读性/一致性。使用unfoldM :: Monad m => m (Maybe a) -> m [a] :

import Control.Monad (liftM, mfilter)
import Control.Monad.Loops (unfoldM)

myReadListTailRecursive :: IO [String]
myReadListTailRecursive = unfoldM go
where
go :: IO (Maybe String)
go = do
line <- getLine
return $ case line of
"" -> Nothing
s -> Just s

或者使用 MaybeMonadPlus 实例,其中 mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a :

myReadListTailRecursive :: IO [String]
myReadListTailRecursive = unfoldM (liftM (mfilter (/= "") . Just) getLine)

另一个更通用的选项可能是使用 LoopT .

关于haskell - 是否建议以尾递归形式使用递归IO操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47234256/

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