问题

我的代码导致了某种无限递归,所以我决定查看这个帖子(OP正在做与我相同的问题:在无限流上实现尺子函数):

使用’streamInterlift’实现尺子函数

我的代码看起来像这样:

 data Stream a = Cons a (Stream a)

streamRepeat :: a -> Stream a
streamRepeat x = Cons x (streamRepeat x)

interleaveStreams :: Stream a -> Stream a -> Stream a
interleaveStreams (Cons x xs) (Cons y ys) = Cons x (Cons y (streamInterleave xs ys))

ruler :: Stream Integer
ruler = interleaveStreams (streamRepeat 0) (streamMap (+1) $ ruler)
 

现在,事实证明,如果我将interleaveStreams的定义更改为

 interleaveStreams :: Stream a -> Stream a -> Stream a
interleaveStreams (Cons x xs) ys = Cons x (interleaveStreams ys xs)
 

并保留其他所有内容,没有无限递归,它正常工作.据我所知,interleaveStreams的两个版本是等价的.为什么其中一个挂起,而另一个正常工作?

  最佳答案

假设您只需要Cons x (Cons y (streamInterleave xs ys))的头. interleaveStreams的挂起实现仍然说它需要匹配Cons x xsCons y ys来做到这一点.这足以打破一些您可能希望有效的操作,当匹配Cons y ys的值是x的函数.

ruler = interleaveStreams (streamRepeat 0) (streamMap (+1) $ ruler)的情况就是这样!为了简化,streamMap没有改变这方面的任何内容:

 ruler = interleaveStreams (streamRepeat 0) ruler
 

并忽略streamRepeat:

 interleaveStreams (Cons y ys) = Cons 0 (Cons y (streamInterleave xs ys))
ruler = interleaveStreams ruler
 

您可以看到为什么Haskell无法弄清楚y是什么.

另一个选项是使用懒惰模式:

 interleaveStreams (Cons x xs) ~(Cons y ys) = Cons x (Cons y (streamInterleave xs ys))
 

或者你可以给ruler一个头开始:

 ruler = Cons 0 (interleaveStreams (streamMap (+1) ruler) (streamRepeat 0))
 

  相同标签的其他问题

haskell