Haskell相互递归的澄清
我遇到过这些关于相互递归的讨论,最初是在Haskell相互递归的澄清,haskell,types,mutual-recursion,Haskell,Types,Mutual Recursion,我遇到过这些关于相互递归的讨论,最初是在let表达式的上下文中,即let允许绑定相互引用,而不考虑顺序。(见)然后我在维基百科上看到了讨论。这以SML中的数据类型的形式给出了一个示例 datatype 'a tree = Empty | Node of 'a * 'a forest and 'a forest = Nil | Cons of 'a tree * 'a forest 我记得,和是相互递归关系所必需的。它导致了哈斯克尔的这一版本 data Tree a = Empty
let
表达式的上下文中,即let
允许绑定相互引用,而不考虑顺序。(见)然后我在维基百科上看到了讨论。这以SML中的数据类型的形式给出了一个示例
datatype 'a tree = Empty | Node of 'a * 'a forest
and 'a forest = Nil | Cons of 'a tree * 'a forest
我记得,和
是相互递归关系所必需的。它导致了哈斯克尔的这一版本
data Tree a = Empty
| Node (a, Forest a)
data Forest a = Nil
| Cons (Tree a) (Forest a)
我对这一点有直观的理解,但语法很混乱,例如,SML树
... Node of 'a * 'a forest
这是一个元组,对吗?是的,我想我在Haskell的翻译中看到了一个元组
... Node (a, Forest a)
直观地说,这与分支功能相同,在分支功能中,树节点可能具有(一个或多个)子树的整个林,对吗?但是HaskellForest
数据类型基本上在Forest
(属于Tree
元素)列表的头部使用了一个新的Tree
元素,而SML版本似乎使用了*
... Cons of 'a tree * 'a forest
这意味着创建一个元组?一般来说,容易混淆的树
定义,即树
下面可能有一个林
。然后是树的这个定义
data Tree = Leaf | Node Int Tree Tree
其中,子树的问题仅限于两个子树。使用林
是允许一个或多个子节点的唯一方法吗?凭直觉,树下没有森林,相反,它们是森林的一员。一个问题是,是否可以直接使用常规列表
data Forest a = Nil | ForestCons (Tree a) [(Tree a)] deriving (Show)
节点(a,林a)
,尽管Haskell完全合法,但它是单一的。该定义的传统形式是
data Tree' a = Empty'
| Node' a (Forest a)
它包含与树
相同的信息,但不是将节点
构造函数的字段打包到元组中,而是将它们作为字段提供。区别在于,在实际处理该类型的值时,您将编写Node'ht
,而不是Node'(h,t)
同样,您的林
相当于不推荐的表单
data Forest' a = Nil'
| Cons' (Tree a, Forest a)
元组是冗余的data Tree a=Empty | Node a(Forest a)
很好。在SML语法中,'a*'的NodeTree
不是元组,尽管看起来像元组。至于直接使用常规列表,我想你要找的是类型Forest a=[Tree a]
。然后,您可以组合这些类型并编写数据树a=Empty |节点a[Tree a]
您可能会发现GADTSyntax
语言选项很有用;与ADT的这种简写语法不同,它允许您编写一个数据
定义,作为构造函数的类型签名列表,您可以在GHCi中查看这些构造函数,例如:type Node
。在本例中,我将编写数据树a其中{Empty::Tree a;Node::a->Forest a->Tree a;}
和数据林a其中{Nil::Forest a;Cons::Tree a->Forest a->Forest a;}
或未承载表单节点::(a,Forest a)->Tree a
Cons:(Tree a,Forest a)->Forest a
如果包含(不必要的)元组。如果不是给定的元组,Forest
的惯用形式是什么?newtype Forest=Forest{treesList::[Tree]}
。但是您使用Cons(Tree a)(Forest a)
的表单也是惯用的,只是使事情变得不必要的复杂。事实上,即使是一个简单的类型
别名,而不是新类型
。