operator and operand don't agree [tycon mismatch] - sml assuming the wrong list type

十年热恋 提交于 2021-02-10 20:29:49

问题


I have a pretty simple code that's supposed to transform a list of tuples (int * string), into two lists, one list of ints and one list of strings - basically a list of tuples into a tuple of lists.

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

And the error:

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

For some reason the compiler believes val y : string list = unzip_single_string(twopls) is referring to an int list.

Interestingly enough, when I switch the two around, when I change:

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

to

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

The error switches too:

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

For some reason, whatever the second call is, it's going to assume that its whatever the last call's type was. Why is it doing this? How do I overcome this? I made it very clear in the two other functions definitions that they are int lists and string lists respectively, so why does SML think that I'm sending it a string list when I clearly defined it as an int list ?

Thanks!


回答1:


The answer to your question is type inference. You haven't given any type for twopls or an argument type for unzip, and you are calling unzip_single_int(twopls) when you make a value declaration for x. Therefore, SML infers that twopls is an int list, because the type of your function unzip_single_int is int list -> int list, which means it takes an int list as input and returns an int list.

After SML infers that twopls is an int list, you are trying to call unzip_single_string(twopls). However, the type of the function unzip_single_string is string list -> string list, therefore it expects an expression of string list as an input. But now twopls is an int list, so you get a type error.

However, your function definitions don't change anything about the list, they return the exact same list, I'm guessing you want them to return either the first or the second element in the tuple, so you should add that. Your unzip function is supposed to have the type (int * string) list -> int list * string list. Therefore, try to pattern match on the int * string elements you have in your list. Normally you would pattern match a list like x :: xs, but if you know the elements are tuples and if you want to access them, you can pattern match them like (num, str) :: xs, where num is an int variable and str is a string variable. You should be able to figure out the rest. Good luck!



来源:https://stackoverflow.com/questions/28185770/operator-and-operand-dont-agree-tycon-mismatch-sml-assuming-the-wrong-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!