Haskell了解一些功能

时间:2014-05-30 14:29:55

标签: haskell stream

有人可以解释为什么第一个函数生成流"a""aa""aaa" ..? 或者为什么第二个生成前缀流,例如: prefixes [1,2,3..] - > [[],[1],[1,2], [1,2,3]..]

strings = "" : ( map ('a' :) strings )
prefixes (x : xs) = [] : ( map (x :) (prefixes xs) )

2 个答案:

答案 0 :(得分:7)

这些都是非常有趣的"打结"例子。您可以通过仔细跟踪评估来理解它们,确保不会评估太多。你也可以等同地理解它们。有时后者更容易

例如,如果我们考虑strings

的轻微变化
strungs = map ('a':) strungs

我们可以认为答案是strungs如果map ('a':)超过它,那么它就会保持不变。如果我们想象strungs是一个字符串列表(并且必须是类型),那么对该列表执行map ('a':)会添加一个新的' a'在每个元素的前面。

因此,strungs在这样的地图之后没有变化的唯一选择是它是否是任何长度的列表,其中每个元素是无限字符串" aaaaa ..."

现在stringsstrungs非常相似,但它有另一个条件。无论strings是什么,它都必须与"" : map ('a':) strings相同。我们很容易看到我们在这里玩strungs类似的游戏,除了我们不断添加新的空元素。因此,strings必须看起来像

"", "a", "aa", "aaa", "aaaa", ...

因为map ('a':) strings看起来像

"a", "aa", "aaa", "aaaa", "aaaaa", ...

然后预先""使其与我们开始时的相同

"", "a", "aa", "aaa", "aaaa", "aaaaa", ...

答案 1 :(得分:5)

他们都非常相似,所以我只会告诉你strings并让你自己找出prefixes作为练习。

Haskell喜欢既递归又懒惰。懒惰意味着值由 thunks 或未来计算的承诺表示。在评估某些内容时,您可以在GHCi中实际看到它们:

> let strings = "" : map ('a' :) strings
> :print strings
strings = (_t1 :: [[Char]])
> strings !! 0
""
> :print strings
strings = "" : (_t2 :: [[Char]])
> strings !! 1
"a"
> :print strings
strings = "" : "a" :: (_t3 :: [[Char]])
> strings !! 2
"aa"
:print strings
strings = "" : "a" : "aa" : (_t4 :: [[Char]])

每个_tN代表一个指向尚未评估的流的其余部分的指针。您也可以将其可视化,其中_表示指向其余strings的指针

strings
    = "" : map ('a':) strings
      ^--------<------^
    = "" : map ('a':) ("" : _)
           ^--------<-------^
    = "" : ('a':"") : map ('a':) (_)
           ^--------<-------------^
    = "" : "a" : map ('a':) ("a" : _)
                 ^-------<---------^
    = "" : "a" : ('a':"a") : map ('a':) (_)
                 ^---------<-------------^
    = "" : "a" : "aa" : map ('a':) ("aa" : _)
                        ^--------<---------^
    = "" : "a" : "aa" : ('a':"aa") : map ('a':) (_)
                        ^----------<-------------^
    = "" : "a" : "aa" : "aaa" : map ('a':) ("aaa" : _)
                                ^---------<---------^
    = "" : "a" : "aa" : "aaa" : ('a':"aaa") : map ('a':) (_)
                                ^------------<------------^
    = "" : "a" : "aa" : "aaa" : "aaaa" : map ('a':) ("aaaa" : _)
                                         ^---------<----------^
    = ...

希望这是有道理的,每个^-<-^显示_在每次迭代中指向的内容(大致)