Haskell CIS194 Spring 13作业6练习5

时间:2016-05-11 23:07:46

标签: haskell lazy-evaluation

http://www.seas.upenn.edu/~cis194/spring13/hw/06-laziness.pdf

问题是关于代表标尺函数

  

0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,.... 。 。   其中第n个元素在流中(假设第一个元素   对应于n = 1)是2的最大幂,其均分n

我有使用show的工作解决方案,用interleaveStreams显示前20个元素'功能:

data Stream a = Cons a (Stream a)

streamToList :: Stream a -> [a]
streamToList (Cons a b) = a : streamToList b 

instance Show a => Show (Stream a) where
  show = show . take 20 . streamToList

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

ruler :: Stream Integer
ruler = 
  let s n = interleaveStreams' (streamRepeat n) (s (n+1)) 
  in s 0

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

interleaveStreams' :: Stream a -> Stream a -> Stream a
interleaveStreams' (Cons x xs) y = Cons x $ interleaveStreams' y xs

但是我不明白为什么使用interleave函数的标尺不会以Show结束。

1 个答案:

答案 0 :(得分:2)

首先祝贺 - 你解决了 hard 部分;)

对于您的问题:如果您使用interleaveStreams,那么它也会在第二个Cons上进行模式匹配 - 但是如果您查看代码,您会看到第二部分是由以下内容生成的:

let s n = interleaveStreams ... (s (n+1)) 

所以,如果interleaveStreams现在要求生成这个部分的Cons,那么你最终会陷入无限循环

另一个函数通过强制第一个构造函数解决了这个问题,你可以从streamRepeat

一次获得

interleaveStreams:

s 0
= interleaveStreams (streamRepeat 0) (s 1))
{ need both cons }
= interleaveStreams (Cons 0 (streamRepeat 0)) (s 1)
= interleaveStreams (Cons ...) (interleaveStreams (streamRepeat 1) (s 2))
{ the inner interleaveStream needs both Cons again for it's pattern }
= ...

你永远不会找到ConsstreamToList永远无法产生列表缺点然后你就会遇到问题

interleaveStreams':

s 0
= interleaveStreams' (streamRepeat 0) (s 1))
{ need only first Cons for the pattern-match }
= interleaveStreams' (Cons 0 (streamRepeat 0)) (s 1)
= Cons 0 $ interleaveStreams' (s 1) (streamRepeat 0)
= ...

你可以看到Cons / show

中的streamToList是懒惰的快乐路径

稍短

顺便说一下:你可以使用s在没有streamMap内部函数的情况下编写它:

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