提问人:F. Zer 提问时间:9/9/2021 最后编辑:Will NessF. Zer 更新时间:9/10/2021 访问量:80
foldTree 分步评估
foldTree step-by-step evaluation
问:
假设 、 和 a 函数的这些定义:foldTree
Tree
f
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
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 [...])
...
在这一点上,我的问题是:方程推理如何与闭包一起工作?has 的定义 ;但是,这肯定不是在其参数之间。有没有什么技巧可以插入该定义?go
f
答:
2赞
Will Ness
9/9/2021
#1
简单地说,一个定义可以指代范围内的任何名称。
“闭合”是一个在存在突变的情况下更相关的概念。在Haskell中,没有“范围”的概念就足够了。
go
的定义嵌套在 的 中,因此可以访问其参数。换句话说,在 的定义中,在范围内。foldTree
f
go
f
定义可以改写为
{-
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
> foldTree f1 t1
=>
let { f=f1; t=t1 }
in
let { go (Node x ts) = f x (map go ts) }
in go t
=>
....
这些是简单的嵌套 S,因此内部的 S 可以访问外部定义的每个名称。let
为了更容易地了解发生了什么,请尝试首先使用更简单的示例数据(如 、 等)对其进行评估。Node "Alpha" []
Node "Alpha" [Node "Beta" []]
例如,使用
f0 x xs = [x] <> (map ('\t' :) (concat xs))
对收益的评估为Node "Alpha" []
> 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"]
评论
0赞
F. Zer
9/9/2021
非常感谢你,@Will尼斯!!一个问题:在第一个代码块中,你有一个子句和一个表达式,我无法编译它。有没有可能修复它?where
let
0赞
F. Zer
9/9/2021
伟大。现在它运行良好。关于第二块代码,您能告诉我如何使用替换定义吗?那里有很多关键字。有什么诀窍可以理解它吗?let
in
1赞
Will Ness
9/9/2021
每个都只有一个,紧随其后的那个。想象一下括在括号中的内部:。虽然这些 paren 当然不是必需的,但无论如何代码都是这样解析的。let
in
let...in...
let { f=f1; t=t1 } in ( let { go (Node x ts) = f x (map go ts) } in ( go t ) )
0赞
F. Zer
9/9/2021
我明白了内在的来源。但是,我看不出最外层是从哪里来的。您的定义不包括它。你能解释一下吗?let
let
foldTree
0赞
F. Zer
9/9/2021
我想我开始明白了!再次感谢您的帮助。你能告诉我这个评价是否正确吗?
评论