运算符和操作数不同意[tycon mismatch] - sml假设列表类型错误

时间:2015-01-28 06:08:50

标签: sml type-mismatch

我有一个非常简单的代码,它应该将元组列表(int * string)转换为两个列表,一个int列表和一个字符串列表 - 基本上是元组列表中的元组列表列表。

fun unzip_single_int[] : int list = []
|   unzip_single_int(x::xs) : int list =
    x :: unzip_single_int(xs)   


fun unzip_single_string[] : string list = []
|   unzip_single_string(x::xs) : string list =
    x :: unzip_single_string(xs)    


fun unzip[] : (int list * string list) = ([], [])
|   unzip([twopls]) : (int list * string list) =
    let
        val x : int list =  unzip_single_int(twopls);
        val y : string list = unzip_single_string(twopls); (* this is line 28 btw *)
    in
        (x, y)
    end

错误:

zip.sml:28.7-28.52 Error: operator and operand don't agree [tycon mismatch]
  operator domain: string list
  operand:         int list
  in expression:
    unzip_single_int twopls

由于某种原因,编译器认为val y:string list = unzip_single_string(twopls)指的是一个int列表。

有趣的是,当我改变两个时,当我改变时:

val x : int list =  unzip_single_int(twopls);
val y : string list = unzip_single_string(twopls);

val y : string list = unzip_single_string(twopls);
val x : int list =  unzip_single_int(twopls);

错误也会切换:

zip.sml:28.7-28.47 Error: operator and operand don't agree [tycon mismatch]
  operator domain: int list
  operand:         string list
  in expression:
    unzip_single_int twopls

出于某种原因,无论第二次呼叫是什么,它都会假设它的最后一个呼叫的类型是什么。它为什么这样做?我该如何克服这个问题?我在其他两个函数定义中清楚地表明它们分别是int列表和字符串列表,那么为什么SML认为我在将它明确定义为int列表时发送字符串列表?

谢谢!

1 个答案:

答案 0 :(得分:3)

您的问题的答案是类型推断。您尚未获得twopls的任何类型或unzip的参数类型,并且当您为unzip_single_int(twopls)进行值声明时,您正在调用x。因此,SML推断twoplsint list,因为函数unzip_single_int的类型是int list -> int list,这意味着它需要int list作为输入并返回int list

在SML推断twoplsint list后,您正试图致电unzip_single_string(twopls)。但是,函数unzip_single_string的类型为string list -> string list,因此它需要string list的表达式作为输入。但现在twoplsint list,因此您会收到类型错误。

但是,你的函数定义不会改变列表的任何内容,它们会返回完全相同的列表,我猜你希望它们返回元组中的第一个或第二个元素,所以你应该补充一点。您的unzip函数应该具有(int * string) list -> int list * string list类型。因此,请尝试对列表中的int * string元素进行模式匹配。通常你会模仿匹配x :: xs这样的列表,但是如果你知道元素是元组,并且你想要访问它们,你可以像(num, str) :: xs那样模式匹配它们,其中num是一个int变量和strstring变量。你应该能够弄清楚其余部分。祝你好运!