在SML中从树创建列表时出现语法错误

时间:2016-11-15 03:11:05

标签: recursion tree sml

我有以下两种数据类型:

datatype leaf = Slist of string list | Real of real | nil;
datatype 'a tree = Empty |  Node of leaf * 'a tree * 'a tree * 'a tree;

下面的代码遍历所有长度为1/2的树,并形成叶子中的值列表。

fun list12(Empty:'a tree) = nil
  | list12(Node(leaf leaf1, 'a tree a1, 'a tree a2, 'a tree a3)) =
    if (not(a1 = Empty) andalso not(a2 = Empty) andalso not(a3 = Empty))
    then list12(a1)::list12(a2)::list12(a3)
    else leaf1::list12(a1)::list12(a2)::list12(a3);

问题是,我得到语法错误,例如

stdIn:94.59-94.66 Error: syntax error: deleting  TYVAR ID
stdIn:94.71-94.78 Error: syntax error: deleting  TYVAR ID
stdIn:94.83-94.93 Error: syntax error: deleting  TYVAR ID ID
stdIn:94.93-94.97 Error: syntax error: deleting  RPAREN RPAREN EQUALOP
stdIn:94.98-94.102 Error: syntax error: deleting  IF LPAREN
stdIn:94.109-94.116 Error: syntax error: deleting  EQUALOP ID

代码本身并不复杂。基本情况是,如果它为空,则返回null。 如果它没有三个节点,那么我添加叶子的值并递归调用节点上的函数。如果是这样,我只是递归调用节点上的函数而不添加叶子。

它起作用,因为它是空的,它通过在列表中添加nil来结束搜索,这没有任何作用。

我还尝试了其他案例,例如使用and代替andalso,以及其他版本的代码,例如

  | list12(Node(leaf1, Empty, Empty, Empty)) = nil
  | list12(Node(leaf2, a1, Empty, Empty)) = leaf2::list12(a1);
  | list12(Node(leaf3, b1, b2, Empty)) = leaf3::list12(b1)::list12(b2);
  | list12(Node(leaf4, c1, c2, c3)) = list12(c1)::list12(c2)::list12(c3);

但我发现以上情况并不符合所有情况。

有关出现语法错误原因的任何想法吗?

旁注,为什么1.0 = 2.0不起作用,但在摘要中它说它适用于实数?它似乎只适用于整数,而><等也不起作用。

1 个答案:

答案 0 :(得分:2)

语法错误:

  1. 您无法重新绑定df5。它是内置列表类型的保留关键字(即index_list = [df1,df2,df3] value_list = [20,22,28,29,30,31,32,33] namesdf = ['df1','df2','df3'] df5 = pd.concat([x.groupby('IDXType')['Datetime'].min() for x in index_list], axis=1, keys=namesdf).reindex(value_list).rename_axis(None) print (df5) df1 df2 df3 20 2015-01-04 NaT 2015-01-04 22 NaT NaT NaT 28 NaT NaT NaT 29 NaT NaT NaT 30 NaT 2015-01-04 2015-01-06 31 NaT NaT 2015-01-07 32 NaT NaT NaT 33 2015-01-06 NaT NaT = nil)。
  2. 您不需要像nil这样的前缀类型。您可以推断出类型(通过不指定它并让类型检查器猜它),或者使用正确的语法([])对其进行注释。
  3. 假设我们没有解决语法错误,可以通过删除类型注释来进一步依赖推理,并添加一些格式,这就是代码的样子:

    'a tree t1

    输入错误:

    t1 : 'a tree

    查看datatype leaf = Slist of string list | Real of real | Nil; datatype 'a tree = Empty | Node of leaf * 'a tree * 'a tree * 'a tree; fun list12 Empty = [] | list12 (Node(leaf1, a1, a2, a3)) = if (not(a1 = Empty) andalso not(a2 = Empty) andalso not(a3 = Empty)) then list12(a1)::list12(a2)::list12(a3) else leaf1::list12(a1)::list12(a2)::list12(a3); 的类型以及您对! then list12(a1)::list12(a2)::list12(a3) ! ^^^^^^^^^^ ! Type clash: expression of type ! 'a list ! cannot have type ! 'a ! because of circularity 的使用情况,类型检查器必须找到一些op:: : 'a * 'a list -> 'a listlist12(a1)::list12(a2)。这就像找'a那样'a = 'a list。显然,无论x返回什么,每一方都有相同类型的东西。

    一个肮脏而低效的技巧是使用x = x + 1运算符(追加)。一种更简洁的方法是折叠整个树,使得您折叠的函数可以访问整个节点(如in this StackOverflow post from the other day):

    list12

    你可以把它折叠成一个函数 - 这种方法是将遍历逻辑分成@,将累积逻辑分成fun para f e Empty = e | para f e0 (t0 as Node (x, t1, t2, t3)) = let val e1 = f (e0, t0) val e2 = para f e1 t1 val e3 = para f e2 t2 val e4 = para f e3 t3 in e4 end fun isNode (Node _) = true | isNode Empty = false fun list12 t = let fun extract (xs, Empty) = xs | extract (xs, Node (x, t1, t2, t3)) = if isNode t1 andalso isNode t2 andalso isNode t3 then x::xs else xs in para extract [] t end 的辅助函数。

    比较para s

      

    为什么1.0 = 2.0不起作用,但在摘要中它说它适用于实际值?

    我不知道你提到的摘要。这个问题在这里得到解答:Why can't I compare reals in Standard ML?(这个答案最初放在这里,但被移到那里,因为它是一个单独的问题。)