Reputation: 11
I have just started on SML and I am having trouble trying to pass NONE/SOME as parameters to a function.
fun fx (SOME x) (SOME y) f = f x y
| fx (SOME x) (NONE) f = NONE
| fx (NONE) (SOME y) f = NONE
| fx (NONE) (NONE) f = NONE;
fun add x y = x + y;
fx (SOME 2) (SOME 4) add;
What I am trying to do is to add two numbers only if neither values are NONE. But I get the following error:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int -> int -> 'Z option
operand: int -> int -> int
in expression:
((fx (SOME 2)) (SOME 4)) add
If remove the cases for NONE, i.e:
fun fx (SOME x) (SOME y) f = f x y
Then it works alright. I don't know where exactly am I making a mistake. f parameter is not optional, yet it is treating as one.
Upvotes: 1
Views: 143
Reputation: 66371
You've already answered the "how", so I will try and explain the "why".
Look at the type of fx
in the REPL:
val fx = fn : 'a option -> 'b option -> ('a -> 'b -> 'c option) -> 'c option
It produces a 'c option
(it is known from your NONE
cases that the result is an option
type).
(Note that 'a -> 'b -> 'c option
is 'a -> ('b -> ('c option))
, not ('a -> 'b -> 'c) option
.)
Since your first case is f x y
, that must produce an option
type - and add
doesn't.
This is what the error message is trying to say; since SOME 2
and SOME 4
are int option
s, fx (SOME 2) (SOME 4)
has the type (int -> int -> int option) -> int option
(the "operator domain" is int -> int -> int option
), but add
is an int -> int -> int
.
(The use of the word "operator" here is a bit confusing. You get used to it.)
If you want the more generic type 'a option -> 'b option -> ('a -> 'b -> 'c) -> 'c option
, you need to wrap the result (as you've found):
fun fx (SOME x) (SOME y) f = SOME (f x y)
Upvotes: 1