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)
直观地说,这与分支功能相同,在分支功能中,树节点可能具有(一个或多个)子树的整个
,对吗?但是Haskell
Forest
数据类型基本上在
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*'的Node
Tree
不是元组,尽管看起来像元组。至于直接使用常规列表,我想你要找的是
类型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)
的表单也是惯用的,只是使事情变得不必要的复杂。事实上,即使是一个简单的
类型
别名,而不是
新类型