If I define
fun id x = x
Then naturally id
has type 'a -> 'a
Of course, id 0
evaluates to 0
, which makes perfect sense.
Since this makes perfect sense, I should be able to encapsulate it by a function:
fun applyToZero (f: 'a -> 'a) = f 0
With the hope that applyToZero
will have type ('a -> 'a) -> int
and applyToZero id
will evaluate to 0
But when I try to define applyToZero
as above, SML/NJ gives an odd error message which begins:
unexpected exception (bug?) in SML/NJ: Match [nonexhaustive match failure]
raised at: ../compiler/Elaborator/types/unify.sml:84.37
This almost looks like a bug in the compiler itself. Weird, but possible.
But PolyML doesn't like it either (though its error message is less odd):
> fun applyToZero (f: 'a -> 'a) = f 0;
poly: : error: Type error in function application.
Function: f : 'a -> 'a
Argument: 0 : int
Reason: Can't unify int to 'a (Cannot unify with explicit type variable)
Found near f 0
The following does work:
fun ignoreF (f: 'a -> 'a) = 1
with the inferred type ('a -> 'a) -> int
. This shows that it isn't impossible to create a higher order function of this type.
Why doesn't SML accept my definition of applyToZero
? Is there any workaround that will allow me to define it so that its type is ('a -> 'a) -> int
?
Motivation: in my attempt to solve the puzzle in this question, I was able to define a function tofun
of type int -> 'a -> 'a
and another function fromfun
with the desired property that fromfun (tofun n) = n
for all integers n
. However, the inferred type of my working fromfun
is ('int -> 'int) -> 'int)
. All of my attempts to add type annotations so that SML will accept it as ('a -> 'a) -> int
have failed. I don't want to show my definition of fromfun
since the person that asked that question might still be working on that puzzle, but the definition of applyToZero
triggers exactly the same error messages.