【问题标题】:Right rotate of tree in Haskell: how is it work?Haskell中树的右旋转:它是如何工作的?
【发布时间】:2010-06-10 06:17:09
【问题描述】:

我不知道 haskell 语法,但我知道一些 FP 概念(如代数数据类型、模式匹配、高阶函数等)。

谁能解释一下,这段代码是什么意思:

data Tree ? = Leaf ? | Fork ? (Tree ?) (Tree ?)

rotateR tree = case tree of
  Fork q (Fork p a b) c -> Fork p a (Fork q b c)

据我了解,第一行类似于树类型声明(但我并不完全理解)。第二行包括模式匹配(我也不明白为什么我们需要在这里使用模式匹配)。第三行对非 Haskell 开发人员来说是绝对不可读的。我发现 Fork 的定义为 fork (f,g) x = (f x, g x),但我不能再进一步了。

【问题讨论】:

  • 查看 carlmon 对 Fork 的回应。通过一个小的重构,我们可以将 rotateR 重写为一个方程: rotateR (Fork q (Fork p a b) c) = Fork p a (Fork q b c) 然后它的意思就是它所说的。如果将 (Fork q (Fork p a b) c) 传递给 rotateR,对于 q,p,a,b,c 的任何值,您将得到 Fork p a (Fork q b c)。

标签: syntax haskell functional-programming binary-tree


【解决方案1】:

首先数据类型定义不能包含问号,而是普通字母:

data Tree a = Leaf a | Fork a (Tree a) (Tree a)

它定义了一个类型Tree,其中包含一些未进一步指定类型a 的元素。 该树要么是Leaf,包含a 类型的元素,要么是Fork,还包含a 类型的元素和两个子树。子树是包含a 类型元素的Tree 结构。

需要注意的是,Haskell 使用括号纯粹是为了分组,就像在2 * (2+3) 中一样,而不是指定调用函数。调用函数时,参数只写在函数名之后,用空格隔开,如sin 30compare "abc" "abd"

case 语句中,-> 左侧的部分是模式匹配,右侧的部分是函数结果,以防树实际上具有左侧指定的形式。如果树是 Fork(即数据类型定义中的 Fork)并且它的第一个子树是另一个 Fork,则模式 Fork q (Fork p a b) c 匹配。小写字母都只是变量,捕获匹配的树结构的不同部分。所以p 是子树中包含的元素,a 是子树的第一个分支,b 是第二个。

-> 的右侧,Fork p a (Fork q b c),现在从模式匹配中匹配的这些部分构建一个新树。小写变量是左侧匹配的所有树部分,Forks 是数据类型定义中的构造函数。它构建了一个Fork 的树,并具有第二个子树,它也是Fork(括号中的部分)。这棵树的剩余部分只是树的左侧“溶解”的部分。

【讨论】:

    【解决方案2】:

    我认为你误解了 Fork。它不是函数,而是 Tree 类型的构造函数。它本质上是 Tree 数据结构中的一个节点...... Tree 中的每个节点要么是一个 Leaf(有一个值),要么是一个 Fork(有一个值和两个子节点)。

    模式匹配用于转换结构。我的 ASCII 艺术作品不够好,无法为您提供绘图,但它有点上移“左节点”和“右节点”下移。

    注意:我说你可能误解了 Fork,因为fork (f,g) x = (f x, g x) 是完全不同的东西。在这种情况下,它是一个高阶函数,与您的 Tree 结构无关。

    希望对您有所帮助 :), 卡尔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多