2013-11-22 116 views
1

我无法写一个函数类型数组
Int -> IO [Int]Int -> [IO Int]哈斯克尔IO和递归

我有下面的代码不工作:

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

哪里createEI是createEI :: IO Int

做这种事情的最佳方法是什么?

+0

replicateM :: Monad的M =>内部 - >马 - > M [A],研究这种类型 –

回答

5

为了保持它接近你原本

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 

我要把它留给你找出如何使用这个删除显式递归。

+0

但是':'不会有'Int'类型的左参数和'IO Int'类型的右参数吗? – functorial

+0

@ user2529202修正了,你把它明确的绑定到一个名字上去删除它的monadic wrapper – jozefg

+0

'<-'删除了IO,然后你可以用新元素 – jozefg

2

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

+0

我认为这将是更好地坚持到'do'记法,而不是拉姆达,因为我们已经在那。 –

+0

我想确保我可以用一行来回答,而不必重写整个事情或冒险造成混淆。 – randomusername

+0

这不会终止。 –

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 

tersest:

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

应用性:

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