I have defined a function like the following:
let ff (f1: a_function) (f2: a_function) (v0: type1) (v1: type2): type3 = ...
And another function like the following works:
let f: type1 -> type2 -> type3 = ff f1 f2
But another declaration like the following does not work:
let f (v0: type1) (v1: type2): type3 = ff f1 f2
The error message is:
Error: This expression has type
type1 -> type2 -> type3
but an expression was expected of type type3
I have always thought that let f: type1 -> type2 -> type3
is same as let f (v0: type1) (v1: type2): type3
. Could anyone tell me why the first declaration works but not the second?
Thank you very much
PS1: My key question is, given let f (v0: type1) (v1: type2): type3 = ff f1 f2
, isn'开发者_Python百科t the type of f
type1 -> type2 -> type3
?
If let f (v0: type1) (v1: type2): type3 = ff f1 f2
and let f (v0: type1) (v1: type2): type3 = ff f1 f2
returns same type of f
, what is the difference between these 2 signatures?
Well, in your definition of f
you say it takes two arguments of types type1
and type2
and returns a result of type type3
. So the body should have type3
. Instead it has type type1 -> type2 -> type3
as you can see from your definition of f
and that's what the compiler tells you.
Perhaps what you meant is:
let f (v0: type1) (v1: type2): type3 = ff f1 f2 v0 v1
Considering your PS the type of f
is not what you say because f
doesn't type-check. I tried to answer why above. If you omitted return type of f
like this:
let f' (v0: type1) (v1: type2) = ff f1 f2
then the type of f'
would be type1 -> type2 -> type1 -> type2 -> type3
.
Arguments v0
, v1
of your second definition are dangling. This declaration works, on the other hand:
module type TimurTest =
sig
type type1
type type2
type type3
type functional1
type functional2
val f1 : functional1
val f2 : functional2
val ff : functional1 -> functional2 -> type1 -> type2 ->type3
end
module MyTest(M:TimurTest) =
struct
let f : M.type1 -> M.type2 -> M.type3 = M.ff M.f1 M.f2
let f (v0: M.type1) (v1: M.type2) : M.type3 = M.ff M.f1 M.f2 v0 v1
let g (v0: M.type1) (v1: M.type2) = M.ff M.f1 M.f2
end
The last line answers your PS (notice I haven't specified the return type of g
, to let the compiler infer what it should be): since its definition ignores arguments v0
and v1
, the curried meaning of g (v0:type1) (v1:type2) = ff f1 f2
gives it the type type1 -> type2 -> type1 -> type2 -> type3
. Basically, you require two additional arguments whose value you're going to throw away (not passing them to ff f1 f2
, which is going to require two of its own).
And indeed, when declaring the above module, part of the response of the compiler is:
val g : M.type1 -> M.type2 -> M.type1 -> M.type2 -> M.type3
精彩评论