如何为sml绘制类型推断解析树

时间:2017-06-15 19:27:59

标签: sml

所以我正在进行练习决赛,有问题请我为这个sml代码绘制一个解析树:

fun ff f x y = if (f x y) then (f 3 y) else (f x "zero")

val ff = fn : (int -> string -> bool) -> int -> string -> bool

我理解如何获得这种类型但不太确定如何绘制一个解析树来表示它。

对于我的作业,我们确实做了这样的问题,这更简单: image for my other homework

1 个答案:

答案 0 :(得分:2)

我能想到的最简单的方法是稍微重新格式化代码,并基本上将每个子表达式放在自己的行上。儿童用增加的缩进表示。

让我们举个例子:

fun ff f x y = if (f x y) then (f 3 y) else (f x "zero")

首先,我们需要做一点点贬低。以上相当于:

val ff =
  fn f =>
    fn x =>
      fn y =>
        if (f x y) then (f 3 y) else (f x "zero")

现在,让我们将每个子表达式放在它自己的行上(在这个特定的例子中,parantheses是多余的;没有它们,一切正常):

val ff =
  fn f =>
    fn x =>
      fn y =>
        if
          f
            x
              y
          then
            f
              3
                y
          else
            f
              x
                "zero"

最后,让我们为每个子表达式附加一个类型,但让我们使用类型变量来表示我们还不知道的类型。请注意,我们对相同的事件使用相同的类型变量。例如,x到处都有t3类型。

Subexpression          | Type
---------------------- | ------------------------------------------
val ff =               | t0
  fn f =>              | t1 -> t2
    fn x =>            | t3 -> t4
      fn y =>          | t5 -> t6
        if             | t7 (* the type of the whole `if` expression *)
          f            | t1
            x          | t3
              y        | t5
          then         | t8 (* the type of the whole `then` part *)
            f          | t1
              3        | int
                y      | t5
          else         | t9 (* the type of the whole `else` part *)
            f          | t1
              x        | t3
                "zero" | string

然后,您可以通过注意某些类型变量是等效的或在某些上下文中使用它们来进行进一步的简化。例如,从这三次调用f

  • f x y
  • f 2 y
  • f x "zero"

我们可以收集x必须属于int类型且y必须属于string类型。因此,让我们用x替换t3的{​​{1}}类型,用int替换y的类型,t5,与string。我们到处都这样做:

Subexpression          | Type
---------------------- | ------------------------------------------
val ff =               | t0
  fn f =>              | t1 -> t2
    fn x =>            | int -> t4
      fn y =>          | string -> t6
        if             | t7
          f            | t1
            x          | int
              y        | string
          then         | t8
            f          | t1
              3        | int
                y      | string
          else         | t9
            f          | t1
              x        | int
                "zero" | string

此外,f用作每次传递int的函数。结果也用作函数,并传递string。这意味着t1,即分配给f的类型变量,必须是int -> string -> r0类型,对于我们还不知道的某些r0。我们将所有t1替换为int -> string -> r0

Subexpression          | Type
---------------------- | ------------------------------------------
val ff =               | t0
  fn f =>              | (int -> string -> r0) -> t2
    fn x =>            | int -> t4
      fn y =>          | string -> t6
        if             | t7
          f            | int -> string -> r0
            x          | int
              y        | string
          then         | t8
            f          | int -> string -> r0
              3        | int
                y      | string
          else         | t9
            f          | int -> string -> r0
              x        | int
                "zero" | string

但请注意,r0必须被视为bool,因为f x y的结果用于if表达式的条件部分,所以让&# 39; s将r0替换为bool无处不在:

Subexpression          | Type
---------------------- | ------------------------------------------
val ff =               | t0
  fn f =>              | (int -> string -> bool) -> t2
    fn x =>            | int -> t4
      fn y =>          | string -> t6
        if             | t7
          f            | int -> string -> bool
            x          | int
              y        | string
          then         | t8
            f          | int -> string -> bool
              3        | int
                y      | string
          else         | t9
            f          | int -> string -> bool
              x        | int
                "zero" | string

接下来,整个if表达式的类型必须与then部分的类型相同,else部分的类型必须与t7部分的类型相同。因此t8t9t7必须全部相同。让我们使用t8我们看到t9Subexpression | Type ---------------------- | ------------------------------------------ val ff = | t0 fn f => | (int -> string -> bool) -> t2 fn x => | int -> t4 fn y => | string -> t6 if | t7 f | int -> string -> bool x | int y | string then | t7 f | int -> string -> bool 3 | int y | string else | t7 f | int -> string -> bool x | int "zero" | string

t7

接下来,bool必须是f 3 y类型,因为f x "zero"bool的类型都是Subexpression | Type ---------------------- | ------------------------------------------ val ff = | t0 fn f => | (int -> string -> bool) -> t2 fn x => | int -> t4 fn y => | string -> t6 if | bool f | int -> string -> bool x | int y | string then | bool f | int -> string -> bool 3 | int y | string else | bool f | int -> string -> bool x | int "zero" | string

t6

接下来,bool也必须是if,因为我们会返回Subexpression | Type ---------------------- | ------------------------------------------ val ff = | t0 fn f => | (int -> string -> bool) -> t2 fn x => | int -> t4 fn y => | string -> bool if | bool f | int -> string -> bool x | int y | string then | bool f | int -> string -> bool 3 | int y | string else | bool f | int -> string -> bool x | int "zero" | string 表达式的结果:

t4

接下来,string -> bool必须是Subexpression | Type ---------------------- | ------------------------------------------ val ff = | t0 fn f => | (int -> string -> bool) -> t2 fn x => | int -> string -> bool fn y => | string -> bool if | bool f | int -> string -> bool x | int y | string then | bool f | int -> string -> bool 3 | int y | string else | bool f | int -> string -> bool x | int "zero" | string 类型,因为它的主体类型是:

t2

int -> string -> bool是什么?它必须是正文的类型,即Subexpression | Type ---------------------- | ------------------------------------------ val ff = | t0 fn f => | (int -> string -> bool) -> int -> string -> bool fn x => | int -> string -> bool fn y => | string -> bool if | bool f | int -> string -> bool x | int y | string then | bool f | int -> string -> bool 3 | int y | string else | bool f | int -> string -> bool x | int "zero" | string

t0

最后,ff的{​​{1}}类型必须与分配给ff的值的类型相同。所以:

Subexpression          | Type
---------------------- | ------------------------------------------
val ff =               | (int -> string -> bool) -> int -> string -> bool
  fn f =>              | (int -> string -> bool) -> int -> string -> bool
    fn x =>            | int -> string -> bool
      fn y =>          | string -> bool
        if             | bool
          f            | int -> string -> bool
            x          | int
              y        | string
          then         | bool
            f          | int -> string -> bool
              3        | int
                y      | string
          else         | bool
            f          | int -> string -> bool
              x        | int
                "zero" | string

这是你的最终结果。