Recursion 与递归数据类型的统一

Recursion 与递归数据类型的统一,recursion,types,sml,unification,Recursion,Types,Sml,Unification,在使用递归数据类型作为嵌套结构(如树)之后,我尝试在测试程序中使用recsurive datatyep,但遇到了(另一个对我来说非常神秘的)错误 我的计划是: datatype 'a tree = Leaf of { value : 'a } | Node of { value : 'a, left: 'a tree, right: 'a tree } fun recursivetreebuilder a n = if n = 0 then Leaf a else

在使用递归数据类型作为嵌套结构(如树)之后,我尝试在测试程序中使用recsurive datatyep,但遇到了(另一个对我来说非常神秘的)错误

我的计划是:

datatype 'a tree =
  Leaf of { value : 'a }
| Node of { value : 'a, left: 'a tree, right: 'a tree }


fun recursivetreebuilder a n =
  if n = 0
  then
      Leaf a
  else
      Node (a, recursivetreebuilder(a, n-1), recursivetreebuilder(a, n-1))
因此,该函数应该通过使用递减的
n
s递归调用自身,直到
n
为0,从而构建深度
n
的二叉树

但我得到了这个错误:

Can't unify {left: 'a tree, right: 'a tree, value: 'a} with {value: 'b} *
(Int32.int/int -> 'c) * (Int32.int/int -> 'c) (Field 1 missing) Found near if
<( n, 0) then Leaf(a) else Node( a, recursivetreebuilder( ...), ......)
无法将{left:'a tree,right:'a tree,value:'a}与{value:'b}统一起来*
(Int32.int/int->'c)*(Int32.int/int->'c)(字段1缺失)在if附近发现
单元
错误-在'recon_bintree.sml'中,第12行。
无法将“a”与“a*Int32.int/int(要统一的类型变量发生在类型中)统一,在if附近找到

这里有两个问题

第一个问题是,例如,
{value:'a,left:'a tree,right:'a tree}
是记录类型,而
(a,recursivetreebuilder(a,n-1),recursivetreebuilder(a,n-1))
是元组而不是记录。所以他们不匹配;这就像将
real
传递给一个需要
int
的函数一样

(学究式的旁白:从技术上讲,元组实际上是记录,但非常具体;
(a,b,c)
{1=a,2=b,3=c}的语法糖。)
。在大多数实际应用中,您可以将元组和记录看作是两种相似但完全不同的组合类型的方法。但现在您知道了错误消息为什么会提到“Field
1

第二个问题是,您将函数声明为使用currying(
fun recursivetreebuilder a n=…
),但随后尝试使用元组调用它(
recursivetreebuilder(a,n-1)


一种方法是坚持您的数据类型定义,并使用currying保留函数,并更改所有内容以匹配这些决策:

datatype 'a tree =
  Leaf of { value : 'a }
| Node of { value : 'a, left: 'a tree, right: 'a tree }

fun recursivetreebuilder a n =
  if n = 0
  then
      Leaf { value = a}
  else
      Node { value = a,
             left = recursivetreebuilder a (n-1),
             right = recursivetreebuilder a (n-1) }
或者更改数据类型定义以消除记录类型,并更改函数以消除套用:

datatype 'a tree =
  Leaf of 'a
| Node of 'a * 'a tree * 'a tree

fun recursivetreebuilder (a, n) =
  if n = 0
  then
      Leaf a
  else
      Node (a, recursivetreebuilder(a, n-1), recursivetreebuilder(a, n-1))
或将上述材料混合搭配。(记录对元组问题的修复与当前对元组问题的修复无关。)


顺便说一句,我认为在
案例和
节点
案例中都包含一个值是错误的。根据您当前的定义,不可能让一棵树包含0个或2个元素

相反,我认为你应该要么有空的叶子:

datatype 'a tree =
  Leaf
| Node of 'a * 'a tree * 'a tree
或具有子节点但没有自己值的节点:

datatype 'a tree =
  Leaf of 'a
| Node of 'a tree * 'a tree
或者消除叶和节点之间的区别,并使子节点可选:

datatype 'a tree =
   Node of 'a * 'a tree option * 'a tree option

好吧,我明白。。。或多或少我试着实现你建议的第二个结构,但仍然有错误。。。我错过了什么?我更新了问题。@Lotolmensre:很抱歉。你还有另一个问题,我没有注意到。我现在更新了答案来解释这两个问题。(这次我已经测试过了。)
datatype 'a tree =
  Leaf of 'a
| Node of 'a tree * 'a tree
datatype 'a tree =
   Node of 'a * 'a tree option * 'a tree option