【问题标题】:operator and operand don't agree [tycon mismatch] - sml assuming the wrong list type运算符和操作数不一致 [tycon mismatch] - sml 假设列表类型错误
【发布时间】:2015-01-29 09:35:40
【问题描述】:

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

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列表时却认为我发送的是字符串列表?

谢谢!

【问题讨论】:

  • 很高兴他们在错误消息中使用了非常有用的术语“tycon”!

标签: sml type-mismatch


【解决方案1】:

您的问题的答案是类型推断。您没有为twopls 指定任何类型或为unzip 指定参数类型,当您为x 进行值声明时,您正在调用unzip_single_int(twopls)。因此,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变量和@ 987654346@ 是一个 string 变量。你应该能够弄清楚其余的。祝你好运!

【讨论】:

    猜你喜欢
    • 2018-02-11
    • 1970-01-01
    • 2018-04-28
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 2014-12-30
    相关资源
    最近更新 更多