我想构建一个无限列表,我尝试使用Data.List.iterate
,但我需要传播上下文(传播时上下文会发生变化)。
Data.List.iterate
的类型为(a -> a) -> a -> [a]
我需要像((a, context)->(a->context)) -> (a, context) -> [a]
到目前为止,我只获得了[(a, context)]
而我无法map fst
,因为我会得到类似[1, 12, 123, 1234...]
而不是[1, 2, 3, 4....]
的内容。
答案 0 :(得分:10)
我认为unfoldr
正是您想要的:
Prelude> import Data.List(unfoldr)
Prelude Data.List> :t unfoldr
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Prelude Data.List> let nrs = unfoldr (\n -> Just (n,n+1)) 1
Prelude Data.List> take 10 nrs
[1,2,3,4,5,6,7,8,9,10]
它的工作原理如下:
你必须给它一个函数,它接受一个状态/上下文(上面的b
类型)和:
Just (output,newState)
Nothing
因此,如果您始终返回Just ...
,则会获得[output]
s
答案 1 :(得分:3)
更新:我错过了问题中的map fst
评论,但我无法理解为什么它没有产生预期结果。
您可以使用iterate
并稍后放弃上下文:
iter :: ((a, context)->(a, context)) -> (a, context) -> [a]
iter f x = map fst $ iterate f x
懒惰使得map
不会被进一步应用。只需确保fst . f
参数中的context
是严格的,这样就不会构成大的thunk。
它也可以内联使用,因为它很短:
> take 15 $ map fst $ iterate (\(a,b) -> (b,a+b)) (0,1)
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]