問題

我的程式碼導致了某種無限遞迴,所以我決定檢視這個帖子(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