ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

lazy ruler

2022-06-12 03:00:56  阅读:165  来源: 互联网

标签:tmp lazy Cons Stream ruler streamInterleave streamRepeat


lazy ruler

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

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

instance Functor Stream where
    fmap f (Cons a b) = Cons (f a) (fmap f b)

streamMap :: (a -> b) -> Stream a -> Stream b
streamMap = fmap

streamIterate :: (a -> a) -> a -> Stream a
streamIterate f init = Cons init (streamIterate f (f init))

streamInterleave :: Stream a -> Stream a -> Stream a
-- Error! ***stackoverflow***
-- streamInterleave (Cons a b) (Cons c d) = Cons a (Cons c (streamInterleave b d))
streamInterleave (Cons a b) c = Cons a (streamInterleave c b)

nats = streamIterate (+1) 0


ruler :: Stream Integer

ruler 是无限 Stream,值为 1, 2, 3, 4, 5, ... 的二进制位的最低位 1 的位数

前一些项为:

           1 0

          10 1
          11 0

         100 2
         101 0
         110 1
         111 0

        1000 3
        1001 0
        1010 1
        1011 0
        1100 2
        1101 0
        1110 1
        1111 0

       10000 4
       10001 0
       10010 1
       10011 0
       10100 2
       10101 0
       10110 1
       10111 0
       11000 3
       11001 0
       11010 1
       11011 0
       11100 2
       11101 0
       11110 1
       11111 0

      100000 5
      100001 0
      100010 1
      100011 0
      100100 2
      100101 0
      100110 1
      100111 0
      101000 3
      101001 0
      101010 1
      101011 0
      101100 2
      101101 0
      101110 1
      101111 0
      110000 4
      110001 0
      110010 1
      110011 0
        ...

观察数据可以发现:

ruler = i 
    (r 0) 
    (i 
        (r 1) 
        (i 
            (r 2) 
            (i 
                (r 3) 
                ...
  where
    i = streamInterleave
    r = streamRepeat

于是写个函数无限嵌套调用就行。之前定义的工具函数似乎没有能帮忙递归的。

ruler :: Stream Integer
ruler = tmp 0 where
    tmp :: a -> Stream a
    tmp n = streamInterleave (streamRepeat n) (tmp (n+1))

或者

ruler = tmp streamInterleave (streamMap streamRepeat nats) where
    tmp :: (Stream a -> Stream a -> Stream a) -> Stream (Stream a) -> Stream a
    tmp f (Cons fn b) = f fn (tmp f b)

然而发现并不会停止,过一段时间后栈溢出,说明有无限递归(但 haskell 里面只有递归,好像是句屁话)

最终发现问题出在 streamInterleave 的定义上

streamInterleave :: Stream a -> Stream a -> Stream a
-- Error! ***stackoverflow***
streamInterleave (Cons a b) (Cons c d) = Cons a (Cons c (streamInterleave b d))
-- Correct
streamInterleave (Cons a b) c = Cons a (streamInterleave c b)

原因是上面的实现在模式匹配时需要将第二个参数展开,而第二个参数实际上永远会依赖于子递归,这使得 ruler 调用过程不会停止

Laziness

The other important thing to note is that thunks are evaluated only enough to allow a pattern match to proceed, and no further!

haskell 由模式匹配驱动惰性求值

做完才看到题目下面有 hint:

Homework 7: Laziness

Do you see why you had to make streamInterleave lazy in its second parameter?

真是好题

标签:tmp,lazy,Cons,Stream,ruler,streamInterleave,streamRepeat
来源: https://www.cnblogs.com/human-in-human/p/16367299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有