wiz*_*zup 7 io haskell loops list
我在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)
Run Code Online (Sandbox Code Playgroud)
它工作正常(在ghci)
> getNext 12345
44827
> getNext 44827
45439
Run Code Online (Sandbox Code Playgroud)
虽然我想在我找到答案之前反复调用 getNext,但我认为我应该保留历史,就像我在非monadic世界中所做的那样,所以我可以继续使用最后一个值,以防出现故障.
> 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]
Run Code Online (Sandbox Code Playgroud)
我认为它应该是一个monadic提升版本的迭代,并iterateM_从Control.Monad.Loops 找到,但它没有像我预期的那样工作.没有显示(我认为_后缀意味着丢弃结果,但没有iterateM)
> :t iterate
iterate :: (a -> a) -> a -> [a]
> :t iterateM_
iterateM_ :: Monad m => (a -> m a) -> a -> m b
Run Code Online (Sandbox Code Playgroud)
问题是如何在非monadic迭代中获得[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]
Run Code Online (Sandbox Code Playgroud)
如果您希望您的函数提前终止,而不是返回无限的结果列表,那么您将需要使用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
Run Code Online (Sandbox Code Playgroud)
这将允许您定义停止条件,以便循环可以终止,但在满足终止条件之前,您将不会收到结果.
该unfoldrM函数可以在monad-loops包中找到,但最新版本不断重用原始种子而不是生成器函数生成的种子(我相信这已经修复但没有上传到Hackage).这是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)
Run Code Online (Sandbox Code Playgroud)
这就是你如何使用它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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
335 次 |
| 最近记录: |