Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 从IO Int迭代创建列表,如何?_List_Haskell_Io_Loops - Fatal编程技术网

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

List 从IO Int迭代创建列表,如何?,list,haskell,io,loops,List,Haskell,Io,Loops,我正在处理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

我正在处理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)
虽然我想反复调用getNext直到找到答案,但我认为我应该像在非一元世界中一样保留历史,以便在出现故障时可以从最后一个值继续

> 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]
我认为它应该是迭代尔的一元提升版本,并从Control.Monad.Loops中找到了
iterateM\uuu
,但它没有像我预期的那样工作。没有显示任何内容(我认为后缀表示放弃结果,但没有iterateM)

问题是如何像在非一元迭代中一样获得[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]
main=do

所以你想要的基本上是

iterateM :: Monad m => (a -> m a) -> a -> m [a]
iterateM action a = do
   a' <- action a
   liftM (a':) $ iterateM action a'
iterateM::Monad m=>(a->ma)->a->m[a]
迭代动作a=do

如果希望函数提前终止,而不是返回 无限的结果列表,您将希望使用
unform
而不是
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
这是使用
管道执行此操作的方式,它将允许您
以结果流的形式进行处理,而无需使用惰性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
import Network.HTTP
进口管制
导入Data.List.Split
进口管制
导入控制.Proxy
url=”http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="
抓取器::(代理p)=>Int->()->Producer p字符串IO()
grabber start()=runIdentityP$loop$show start where
循环x=do
--获取下一个值
x'()->消费者个人账户
打印机()=runIdentityP$forever$do
IO字符串
getNext-prev=do
rsp打印机

您如何知道何时找到答案?你在寻找一个特定的值吗?@sabauma我不知道,但我想是的。这就像一个益智游戏。您可以从第一个任务开始,一元绑定不需要严格,
iterateM
将与
Control.Monad.State.Lazy
和其他一些任务一起工作。不过,这些太特殊了,
iterateM
通常不太有用。我不知道这些是否都正确。我是否可以得出这样的结论:不存在模仿IO monad的
iterate
的惰性列表生成?只是好奇,如果列表是一种单子,为什么不是所有的单子都有这个特征呢?啊!我确实忘记了爱娥不仅仅是一个单子,它也不纯洁。所以这就解释了为什么它是不同的。实际上,
IO
是纯的,这不是问题所在。只是,它必须是严格的。谢谢,我会尝试看看这是否可以被采纳。我不知道这个谜题的终止条件<代码>停止
可能没有任何意义。我所拥有的唯一信息是,我必须使用上次返回的值表单不断请求。我认为理想的解决方案应该是lazy IO,这样即使是无限列表,我也可以看到每个返回值从putStr弹出。@wizzup lazy IO通常被认为是错误的做法。这很有诱惑力,但却打开了一罐虫子。我添加了一些关于如何使用
管道执行此操作的代码,您可能会发现这些代码很有用。
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
-- |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)
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