问题
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