带有上下文传播的无限列表

时间:2016-04-19 16:21:31

标签: haskell

我想构建一个无限列表,我尝试使用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....]的内容。

2 个答案:

答案 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]