【问题标题】:Haskell CIS194 Spring 13 Homework 6 Exercise 5Haskell CIS194 Spring 13 作业 6 练习 5
【发布时间】:2016-05-11 23:07:45
【问题描述】:

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 终止。

【问题讨论】:

    标签: haskell lazy-evaluation


    【解决方案1】:

    首先恭喜 - 你解决了 困难 部分;)

    对于您的问题:如果您使用 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)
    = ...
    

    如您所见,Consshow/streamToList 中懒惰的快乐之路


    短一点

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

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

    【讨论】:

      猜你喜欢
      • 2015-05-01
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多