我在Haskell中编写一个递归函数,它将元组列表作为输入并返回一个元组。返回的元组的第一部分应该是列表中元组的数量,返回的元组的第二部分应该是列表中每个元组的所有元素。在这里清除它是一个示例运行应该是什么样的:
gather [ (0, [true, true] ), (1, [true, false] ), (2, [false, true]) ]
returns (3, [true, true, true, false, false, true] )
我对Haskell相当新,但这是我对递归代码的尝试:
gather [()] = [()]
gather n as = head as : gather n (take n as)
tupList :: [(a)] -> [(a)]
tupList n xs = map (\x -> gather n (take x xs)) [n..]
编译器完全不喜欢这个,有什么建议可以解决这个问题吗?谢谢你的时间!
答案 0 :(得分:1)
首先让我给你一个工作版本(我希望这不是功课):
gather :: [(a,[b])] -> (Int, [b])
gather xs = (length xs, concatMap snd xs)
现在到你的版本:
首先你没有给出签名,但gather
的两个案例已经在参数数量上有所不同(第一个有[()] -> [()]
类型,第二个类似Int -> [a] -> [a]
(你是什么)真正想要的就是我给出的 - 或者我根据你的例子猜测。)
接下来的想法是,我不知道你要对gather
做些什么 - 如果你解释你的想法,我会试着让你走上正轨。
根据您的需要tupList
,我不知道。
我知道你想要一个递归功能 - 但如果是作业,这只是首选IMO ...所以我感觉没有给你一个递归版本... ...如果你想要你可以使用递归重写concatMap
部分(或length
)。
我认为你想做正确的思考:将问题分成两部分:连接列表和计算项目。
计算项目非常简单:要么使用length
,要么重新定义它:
length :: [a] -> Int
length [] = 0
length (_:tl) = 1 + length tl
第一个问题应该是这样的:
concat :: [[a]] -> [a]
concat [] = []
concat (xs:xss) = undefined
也许你可以尝试自己填写(最有可能你使用(++)
)
如果你将它重写为:
,你可以像我一样做gather ts = (length ts, concat (map snd ts))
λ> gather [(0, [True, True] ), (1, [True, False] ), (2, [False, True])]
(3,[True,True,True,False,False,True])
答案 1 :(得分:0)
这是一个递归版本。它只在输入列表中执行一次传递。做两次独立的通行证往往会导致空间泄漏。
gather xs = g 0 xs
where
g c [] = (c, [])
g c ((_,ys):r) = (a, ys ++ b)
where
(a,b) = c `seq` g (c+1) r
当我们沿着列表前进时, seq
会导致立即计算计数器。如果没有它,c+1
的计算可能会被不必要地延迟。
实际上这是保护的递归。