gpt4 book ai didi

list - 从 IO Int 迭代列表创建,如何?

转载 作者:行者123 更新时间:2023-12-04 11:40:26 24 4
gpt4 key购买 nike

我在玩linkedlist python挑战中需要查询下一个值的问题(猜测它是Int)。

我创建函数来获取下一个值,如下所示

url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=" 

getNext :: Int -> IO Int
getNext x = do
rsp <- simpleHTTP (getRequest $ url ++ show x)
bdy <- getResponseBody rsp
let num = last $ splitWhen (==' ') bdy
return (read num::Int)

它工作正常(在ghci中)
> getNext 12345
44827
> getNext 44827
45439

虽然我想反复调用 getNext 直到找到答案,但我认为我应该像在非单子(monad)世界中那样保留历史记录,这样我就可以从最后一个值继续,以防出现故障。
> let nX x = x + 3
> :t nX
nX :: Num a => a -> a
> take 10 $ iterate nX 1
[1,4,7,10,13,16,19,22,25,28]

我认为它应该是迭代的单子(monad)提升版本,发现 iterateM_来自 Control.Monad.Loops 但它没有像我预期的那样工作。没有显示(我认为 _ 后缀意味着丢弃结果但没有 iterateM)
> :t iterate
iterate :: (a -> a) -> a -> [a]
> :t iterateM_
iterateM_ :: Monad m => (a -> m a) -> a -> m b

问题 是如何在非单子(monad)迭代中获得 [Int] 。我想我想要一个返回 IO [Int] 的函数能够像这样在我的代码中提取和过滤/处理
main = do
i <- getAllList
let answer = last i -- or could be a repeated converged value, don't know yet
putStrLn (show answer)

getAllList :: IO [Int]

最佳答案

如果您希望您的函数提前终止,而不是返回一个
无限的结果列表,您将需要使用 unfoldrM而不是iterateM .这可以通过以下方式完成:

url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=" 


start = 12345
stop = 10000

shouldStop :: Int -> Bool
shouldStop x = x == stop

getNext :: Int -> IO (Maybe (Int, Int))
getNext prev
| shouldStop prev = return Nothing
| otherwise = do
rsp <- simpleHTTP (getRequest $ url ++ show prev)
bdy <- getResponseBody rsp
let num = read $ last $ splitWhen (==' ') bdy :: Int
print (prev, num)
return $ Just (num, num)

getAllList :: IO [Int]
getAllList = unfoldrM getNext start

这将允许您定义一个停止条件,以便循环可以
终止,但在终止之前您不会收到结果
已满足标准。
unfoldrM功能可以在 monad-loops中找到包,但
最新版本继续重用原始种子,而不是由
生成器功能(我相信这已经修复但没有上传到
黑客攻击)。这是 unfoldrM 的版本你想要的。
-- |See 'Data.List.unfoldr'.  This is a monad-friendly version of that.
unfoldrM :: (Monad m) => (a -> m (Maybe (b,a))) -> a -> m [b]
unfoldrM = unfoldrM'

-- |See 'Data.List.unfoldr'. This is a monad-friendly version of that, with a
-- twist. Rather than returning a list, it returns any MonadPlus type of your
-- choice.
unfoldrM' :: (Monad m, MonadPlus f) => (a -> m (Maybe (b,a))) -> a -> m (f b)
unfoldrM' f z = go z
where go z = do
x <- f z
case x of
Nothing -> return mzero
Just (x, z) -> do
xs <- go z
return (return x `mplus` xs)

这就是你可以使用 Pipes 的方法。 ,这将允许您
在不使用惰性 I/O 的情况下将处理作为结果流进行。
import Network.HTTP
import Control.Monad
import Data.List.Split
import Control.Monad
import Control.Proxy

url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="

grabber :: (Proxy p) => Int -> () -> Producer p String IO ()
grabber start () = runIdentityP $ loop $ show start where
loop x = do
-- Grab the next value
x' <- lift $ getNext x
-- Send it down stream
respond x'
-- Keep grabbing
loop x'

-- Just prints the values recieved from up stream
printer :: (Proxy p, Show a) => () -> Consumer p a IO r
printer () = runIdentityP $ forever $ do
a <- request () -- Consume a value
lift $ putStrLn $ "Received a value: " ++ show a

getNext :: String -> IO String
getNext prev = do
rsp <- simpleHTTP (getRequest $ url ++ prev)
bdy <- getResponseBody rsp
let num = last $ splitWhen (== ' ') bdy
return num

main = runProxy $ grabber start >-> printer

关于list - 从 IO Int 迭代列表创建,如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14731863/

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