【问题标题】:Implementing the ruler function using `streamInterleave`使用 `streamInterleave` 实现标尺功能
【发布时间】:2019-03-25 02:57:36
【问题描述】:

我正在做CIS 194的作业。问题是使用streamInterleave实现标尺功能。代码看起来像

data Stream a = Cons a (Stream a)

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

streamMap :: (a -> b) -> Stream a -> Stream b
streamMap f (Cons x xs) = Cons (f x) (streamMap f xs)

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

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

我真的很困惑为什么可以这样实现标尺。这是要给我[0,1,0,1....]吗?

任何帮助将不胜感激。谢谢!!

【问题讨论】:

  • 你到底卡在哪一部分?除了实际的 ruler 定义之外,您是否了解其中的大部分内容,或者您​​是否还需要了解其他各种 streamXXX 函数的帮助?
  • 因在家庭作业上诚实而被赞成。不,标尺不会导致0,1,0,1,...,因为在这种情况下streamMap (+1) ruler 将是1,2,1,2,...,并且与0,0,0,... 交错不会导致0,1,0,1,...。这更棘手。不过,0,1 看起来是正确的开始。尝试为某些未知数 xi 假装 ruler=0,1,x2,x3,x4,x5,...,并尝试推断 x2 应该是什么。然后,知道x2,计算x3。等等。你会注意到一个模式。

标签: haskell stream infinite self-reference interleave


【解决方案1】:

首先,我们将像这样表示Stream

a1 a2 a3 a4 a5 ...

现在,我们把ruler的定义拆开:

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

在 Haskell 中,很重要的一点是惰性;也就是说,在需要评估之前,不需要评估东西。这在这里很重要:这就是使这个无限递归定义起作用的原因。那么我们如何理解这一点呢?我们将从streamRepeat 0 位开始:

0 0 0 0 0 0 0 0 0 ...

然后将其馈入streamInterleave,将其与来自streamMap (+1) ruler(表示为xs)的(尚未知的)流交错:

0 x 0 x 0 x 0 x 0 x 0 x ...

现在我们将开始填写那些xs。我们已经知道ruler 的每个第二个元素是0,所以streamMap (+1) ruler 的每个第二个元素必须是1

  1   x   1   x   1   x   1   x   1   x ... <--- the elements of (streamMap (+1) ruler)
0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x ... <--- the elements of ruler

现在我们知道每四个一组中的第二个元素(所以数字 2,6,10,14,18,...)是 1,所以 streamMap (+1) ruler 的对应元素必须是 2

  1   2   1   x   1   2   1   x   1   2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 x 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler

现在我们知道每组 8 个元素中的每四个元素(所以数字 4、12、20、...)是 2,所以 streamMap (+1) ruler 的对应元素必须是 3

  1   2   1   3   1   2   1   x   1   2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 3 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler

我们可以继续像这样无限构建ruler,方法是将ruler的每个n/2, 3n/2, 5n/2, ...编号值替换回来。

【讨论】:

    【解决方案2】:

    在 Haskell 表示法中,用 [] 代替 Stream 与无限列表同构),

    ruler = interleave (repeat 0) 
                       (map (+1) ruler)
    
    [ruler !! i     | i <- [0..]]     == concat . transpose $
                                           [ repeat 0
                                           , map (+1) ruler]
    

    ruler分成两个交替的子序列进行匹配,我们得到

    [ruler !! 2*i   | i <- [0..]]     == repeat 0
                                      == [0 | i <- [0..]]         -- {0} --
    
    [ruler !! 2*i+1 | i <- [0..]]     == map (+1) ruler
                                      == map (+1) $ concat . transpose $
                                           [ [ruler !! 2*i   | i <- [0..]]
                                           , [ruler !! 2*i+1 | i <- [0..]]]
    concat . transpose $              == concat . transpose $
     [[ruler !! 2*i+1 | i <- [0,2..]]      [ [1 | i <- [0..]]
     ,[ruler !! 2*i+1 | i <- [1,3..]]]     , [1 + ruler !! 2*i+1 | i <- [0..]]]
    

    再次分裂,

      [ruler !! 4*i+1 | i <- [0..]]   == [1 | i <- [0..]]         -- {1} --
    
      [ruler !! 4*i+3 | i <- [0..]]   == concat . transpose $
                                           [ [1 + ruler !! 2*i+1 | i <- [0,2..]]
                                           , [1 + ruler !! 2*i+1 | i <- [1,3..]]]
    

    再一次,

      [ruler !! 8*i+3 | i <- [0..]]   == [2 | i <- [0..]]         -- {2} --
    
      [ruler !! 8*i+7 | i <- [0..]]   == ....
    

    你应该可以从这里看透它:

          .... 16*i+7             .....   3                       -- {3} --
          .... 32*i+15            .....   4                       -- {4} --
          .... 64*i+31            .....
          ....
    

    因此,

        ruler !! 2^(k+1)*i + 2^k - 1   ==   k    ,  k <- [0..] ,  i <- [0..]
    
    0: i => 2i
    1:      2i+1 => 4i+1
    2:              4i+3 => 8i+3
    3:                      8i+7 => 16i+7
    4:                              16i+15 => ....
    5:                                     
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多