【问题标题】:Haskell IO and arrays with recursionHaskell IO 和递归数组
【发布时间】:2013-12-06 19:57:49
【问题描述】:

我在编写类型为
Int -> IO [Int]Int -> [IO Int] 的函数时遇到问题

我的以下代码不起作用:

createEIList :: Int -> IO [Int]
createEIList len = do
    cur <- createEI
    (return cur):(createEIList (len-1))

createEI 是createEI :: IO Int

做这样的事情最好的方法是什么?

【问题讨论】:

  • replicateM :: Monad m => Int -> m a -> m [a],研究这个类型

标签: arrays haskell recursion io functional-programming


【解决方案1】:

最后一行应该是createEIList (len-1) &gt;&gt;= \a -&gt; return (cur:a)

【讨论】:

  • 我认为最好坚持使用do-notation 而不是 lambda,因为我们已经这样做了。
  • 我想确保我可以在一行中回答,而不必重写整个内容或冒着造成混乱的风险。
  • 这不会终止。
  • @dave 我认为如果您添加一个长度为 0 的案例,即。 createEIList 0 = return []?
  • 没有 lambda - createEIList (len-1) &gt;&gt;= return . (cur :)
【解决方案2】:
createEIList :: Int -> IO Int    
createEIList len = createEI >>= return . replicate len

createEIList :: Int -> IO Int  
createEIList len = createEI >>= replicateM len . return

更好的解决方案:

createEIList :: Int -> IO Int
createEIList len = replicateM len createEI

最有趣的:

createEIList :: Int -> IO Int
createEIList = flip replicateM createEI

应用:

import Control.Applicative
createEIList  len = replicate <$> pure len <*> createEI
createEIList' len = liftA2 replicate (pure len) createEI

【讨论】:

    【解决方案3】:

    为了让它接近你原来拥有的东西

    createEIList :: Int -> IO [Int]
    createEIList len = do
        cur <- createEI
        rest <- createEIList (len-1)
        return (cur:rest)
    

    这样,您不会尝试将IO Int 附加到您的列表中,而是将整个列表返回将您的[Int] 提升到IO [Int]

    您可能还需要一个基本案例

    createEIList 0 = return []
    createEIList n = ...
    

    这样递归实际上就终止了。

    另外值得注意的是,您可以使用组合器删除显式递归

     replicateM :: Int -> IO a -> IO [a] -- Restricted for clarity
    

    我会让你弄清楚如何使用它。

    【讨论】:

    • 但是: 不会有Int 类型的左参数和IO Int 类型的右参数吗?
    • @user2529202 已修复,您将其显式绑定到名称以删除它的一元包装器
    • &lt;- 删除了 IO,然后你可以用新元素来 cons 它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 2017-01-20
    • 2010-10-13
    相关资源
    最近更新 更多