【发布时间】:2016-06-27 19:07:26
【问题描述】:
Haskell noob here:我仍在尝试理解该语言的机制,所以如果我的问题很愚蠢,请原谅我并指出我可以从中学习的一些链接(我在类似的主题中搜索了一段时间在stackoverflow上,但我仍然无法得到这个)。
我想出了这个功能:
chunks :: Int -> [a] -> [[a]]
chunks n xs
| length xs <= n = [xs]
| otherwise = let (ch, rest) = splitAt n xs in ch:chunks n rest
这样
ghci> chunks 4 "abracadabra"
["abra","cada","bra"]
ghci>
ghci> chunks 3 [1..6]
[[1,2,3],[4,5,6]]
我对此非常满意,然后我想“有惰性评估!我什至可以在无限序列上使用它!”。所以我尝试了take 4 $ chunks 3 [1..]。我希望懒惰的 haskell 魔法会产生[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],相反,这一次懒惰似乎无法帮助我:它无法到达计算的终点(它是一直走到终点吗? [1..]?)
我认为问题出在“长度 xs”部分:ghci 似乎也卡在了一个简单的 length [1..] 上。所以我在问:长度实际上是在迭代整个列表以给出响应吗?如果是这样,我想每次我尝试实现与惰性评估一起工作的东西时都要避免长度,所以有一些替代方案吗?
(例如,如何改进我的示例以使用无限列表?)
【问题讨论】:
-
回答你自己问题的方法当然是追踪
length的实现(参见haskell标签信息部分的资源),或者更好地尝试自己定义它并说服自己它只能以一种方式表现。 -
如果您喜欢冒险,请尝试用Peano numbers 而不是
Int重新实现splitAt和length,看看您是否可以使您的chunks好-表现在无限列表中 -
您可能想看看
genericLength和懒惰的Natural类型——只需将chunks类型中的Int更改为Natural并将length更改为@987654341 @ 将使您的示例有效。
标签: haskell lazy-evaluation infinite