开发者

Signature of the declaration of a function in Ocaml

开发者 https://www.devze.com 2023-03-20 21:01 出处:网络
I have defined a function like the following: let ff (f1: a_function) (f2: a_function) (v0: type1) (v1: type2): type3 = ...

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
0

精彩评论

暂无评论...
验证码 换一张
取 消