1

このコードで遊んでいましたが、何かわかりません。

type t1 = [ `A ];;
type t2 = [ t1 | `B ] ;;
type t3 = [ t2 | `C ] ;;

module type MT =
sig
  type ('a,'b) fct
  val create : ('a -> 'b) -> ('a,'b) fct
end;;

module Mt : MT =
struct
    type ('a,'b) fct = 'a -> 'b
    let create f = f
end;;

let f = (fun x -> x : t2 -> t2) ;;
let af = Mt.create (fun x -> x : t2 -> t2);;

(f :> t1 -> t3);;
(af :> (t1, t3) Mt.fct);;

このように、コンパイラは Mt.fct の型パラメーターが共変か反変かを知らないため、機能しません。ただし、モジュール署名の型宣言を次のように置き換えると:

type (-'a,'+b) fct

b が共変で反変であることをコンパイラに伝えると、今では機能します。そして、私は狡猾でうっとうしい男の子なので、コンパイラに a も共変だと言って嘘をつきました!

type (+'a,'+b) fct

でも彼は私より頭がいいし、私が嘘をついていることに気づいている。

Type declarations do not match:
         type ('a, 'b) fct = 'a -> 'b
       is not included in
         type (+'a, +'b) fct
       Their variances do not agree.

私の質問は次のとおりです:もし彼がとにかく型パラメータの分散を知っているなら、+と-を強制的に追加するのではなく、モジュールにそれを使用しないのはなぜですか. それは再び決定可能性の問題ですか?

4

2 に答える 2

0

コンパイラは、特定の引数位置で型が実際に共変か反変かをチェックできますが、これが抽象型で公開したい情報であるとすぐには判断しません。結局のところ、コンパイラがパラメーターの差異を認識すると、必要に応じてそのパラメーターに対して強制を実行できるようになります。これは、パブリック API の一部ではない可能性があります。

于 2015-02-16T02:12:18.817 に答える