首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >foldTree逐步评估

foldTree逐步评估
EN

Stack Overflow用户
提问于 2021-09-09 13:28:28
回答 1查看 78关注 0票数 1

假设foldTreeTree和函数f的这些定义

代码语言:javascript
复制
foldTree : (a -> [b] -> b) -> Tree a -> b
foldTree f = go
    where
        go (Node x ts) = f x (map go ts)

tree :: Tree String
tree = Node
      "Alpha"
      [ Node "Beta" [Node "Epsilon" [], Node "Zeta" [], Node "Eta" []]
      , Node "Gamma" [Node "Theta" []]
      , Node "Delta" [Node "Iota" [], Node "Kappa" [], Node "Lambda" []]
      ]

f x xs = [x] <> (map ('\t' :) (concat xs))

我将尝试评估foldTree f tree

代码语言:javascript
复制
  foldTree f tree
= go (Node "Alpha" [ Node "Beta" [Node "Epsilon" [], Node "Zeta" [], Node "Eta" []], Node "Gamma" [Node "Theta" []], Node "Delta" [Node "Iota" [], Node "Kappa" [], Node "Lambda" []]]
= f "Alpha" (map go [...])
...

此时,我的问题是:等式推理是如何与闭包一起工作的?go的定义有f;但是,在它的参数之间肯定不是这样。有什么诡计允许插入这个定义吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-09 13:36:39

简单地说,定义可以引用范围内的任何名称。

“闭包”是一个在突变的情况下更相关的概念。在没有“范围”的Haskell中,“范围”的概念就足够了。

go的定义嵌套在foldTree的定义中,因此可以访问它的参数f,换句话说,在go的定义中,f在范围内。

定义可以重写为

代码语言:javascript
复制
{-
foldTree f t = go t
    where
         go (Node x ts) = f x (map go ts)
-}
foldTree f t =
   let { go (Node x ts) = f x (map go ts) } 
   in go t

而任何调用foldTree f1 t1都被计算为

代码语言:javascript
复制
> foldTree f1 t1 
=>
  let { f=f1; t=t1 }
  in
    let { go (Node x ts) = f x (map go ts) } 
    in go t
=>
  ....

这些都是简单的嵌套let,因此内部可以访问外部名称所定义的每个名称。

为了更容易地了解正在发生的事情,首先尝试使用一个简单的示例数据(如Node "Alpha" []Node "Alpha" [Node "Beta" []]等)对其进行评估。

例如,用

代码语言:javascript
复制
f0 x xs = [x] <> (map ('\t' :) (concat xs))

Node "Alpha" []的评估进展如下

代码语言:javascript
复制
> foldTree f0 (Node "Alpha" []) 
=>
  let { f=f0; t=Node "Alpha" [] }
  in
    let { go (Node x ts) = f x (map go ts) } 
    in go t
=>
  let { f x xs = [x] <> (map ('\t' :) (concat xs))
      ; go (Node x ts) = f x (map go ts) 
      } 
  in go (Node "Alpha" [])
=>
  let { f x xs = [x] <> (map ('\t' :) (concat xs))
      ; go (Node x ts) = f x (map go ts) 
      ; (Node x1 ts1) = (Node "Alpha" [])
      } 
  in f x1 (map go ts1)
=>
  let { f x xs = [x] <> (map ('\t' :) (concat xs))
      ; go (Node x ts) = f x (map go ts) 
      ; x1 = "Alpha"
      ; ts1 = []
      ; xs1 = map go ts1
      } 
  in [x1] <> (map ('\t' :) (concat xs1))
=>
  ["Alpha"] <> (map ('\t' :) (concat []))
=>
  ["Alpha"] <> (map ('\t' :) [])
=>
  ["Alpha"] <> []
=>
  ["Alpha"]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69119099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档