6

次のように、フォーマット可能なセットのファンクターを作成しました。

module type POrderedType =
  sig
    type t
    val compare : t -> t -> int
    val format : Format.formatter -> t -> unit
  end

module type SET =
  sig
    include Set.S
    val format : Format.formatter -> t -> unit
  end

module MakeSet (P : POrderedType) : SET with type elt = P.t

これの実装は簡単です:

module MakeSet (P : OrderedType) =
  struct
    include Set.Make(P)

    let format ff s =
      let rec format' ff = function
        | [] -> ()
        | [v] -> Format.fprintf ff "%a" format v
        | v::tl -> Format.fprintf ff "%a,@ %a" format v format' tl in
      Format.fprintf ff "@[<4>%a@]" format' (elements s)
  end

私は地図で似たようなことをしたいと思っていました。 POrderedTypeキーには問題ありませんが、値にはもっと単純な型が必要です:

module type Printable =
  sig
    type t
    val format : Format.formatter -> t -> unit
  end

次に、セットで行ったことと同様のことをしたかったのですが、次の問題に遭遇しました。 Map.S値には type があり+'a tます。Map.Sを に制約しながら定義を含める方法がわかりませ'aPrintable.t。私が欲しいのは、次のようなものです(違法であるという事実を無視して):

module MakeMap (Pkey : POrderedType) (Pval : Printable) :
  MAP with type key = Pkey.t and type 'a t = 'a t constraint 'a = Pval.t

Map の署名全体を手動でコピーせずに、やりたいことを行う方法はありますか?

4

1 に答える 1

3

ポリモーフィック マップの印刷関数を提案する最もクリーンな方法は、値の印刷関数に対してマップの印刷関数をパラメトリックにすることだと思います。次のように考えることができます。

  • ファンクター定義型はファンクター レベルで定義されるため、新しいファンクター パラメーターを追加する (または既存のパラメーターを強化する) ことによって、関数を提供するのが最適です。

  • パラメトリック型は値レベルでバインド (一般化) されるため、それらに関数を提供するには、値に新しいパラメーターを追加するのが最適です。

OCaml では、利便性のために、可能であれば関数化よりもパラメトリック ポリモーフィズムを好む傾向があります。関数化は、型の安全性を強制するために必要になる場合があります (ここでは、異なる比較関数のマップに互換性のない型があることを確認するために使用されます)。つまり、あなたは実際にここで幸運な状況にいます。

モノモルフィック マップを作成するファンクタが本当に必要な場合は、残念ながら、マップ インターフェイス全体をコピーして、それをモノモルフィック ケースに適合させる必要があります。これはたいした作業ではありません。

于 2012-10-15T05:44:50.327 に答える