3

次のシグネチャを使用して、文字列と配列 (実際にはインデックス可能な型) に対してコードをジェネリックにしたいと思います。

module type Indexable = sig
  type 'a t
  val get : int -> 'a t -> 'a
end

module MyCode (I : Indexable) = struct ... end

しかしもちろん、次のように署名を文字列に適用することはできません。

module StrMyCode = MyCode(struct
  type 'a t = string
  let get i a = a.[i]
end)

この問題を解決する方法はありますか? それとも別のアプローチですか?最悪の場合、文字の配列を使用できることはわかっていますが、コードを醜いキャストから救いたいと思っています。

4

3 に答える 3

6

GADTは、機能化されたアプローチで使用できます。

module type Indexable = sig
  type 'a t
  val get: int -> 'a t -> 'a
end

module MyCode(I:Indexable) = struct
 let head x = I.get 0 x
end

もちろん、配列は簡単に作成できIndexableます。

module IndexableArray = struct
  type 'a t = 'a array
  let get i x = x.(i)
end

文字列の場合、単一のコンストラクターでGADTを使用できます。ただし、ポリモーフィック型を強制するために、getに型注釈を付ける必要があることに注意してください(そうでない場合、推測される型はint -> char t -> char):

module IndexableString = struct
  type 'a t = String: string -> char t
  let of_string s = String s
  let get: type a. int -> a t -> a =
    fun i s -> match s with String s -> s.[i]
end
于 2013-01-13T11:49:03.470 に答える
5

これが私がGADTを使って作ったものです。頭を包んでいるだけなので、少しおかしいかもしれません。しかし、私が見る限り(OCaml 4で)動作しているようです:

type _ indexable =
    | A : 'a array -> 'a indexable
    | C : string -> char indexable

let index (type s) (x: s indexable) i : s =
    match x with
    | A a -> a.(i)
    | C s -> s.[i]

let main () =
    let x = A [| 1; 2 |] in
    let y = C "abc" in
    Printf.printf "%d\n" (index x 0);
    Printf.printf "%c\n" (index y 1)

トップレベルにロードすると、次のようになります。

val index : 'a indexable -> int -> 'a = <fun>
val main : unit -> unit = <fun>
# main ();;
1
b
- : unit = ()
#

これはあなたが探しているものほど一般的ではないかもしれません。

于 2013-01-12T01:31:19.787 に答える
2

インデックス可能な要素の型を別の型として宣言すると、次のようなことができます。

module type Indexable = sig
  type t
  type elt
  val get : int -> t -> elt
end

module IndexableString : Indexable = struct
  type t = string
  type elt = char
  let get i a = a.[i]
end

module MyCode (I : Indexable) = struct
  (* My code implementation *)
end

module StrMyCode = MyCode(IndexableString)

配列の場合、多かれ少なかれ同じことができます。

module ArrayIndexable = struct
    type elt = char
    type t = char array
    let get i a = a.(i)
end

ここで、配列である程度の柔軟性を維持したい場合は、上記をファンクターに変更できます。

module ArrayIndexable (E : sig type e end) : Indexable with type elt = E.e =
struct
    type elt = e
    type t = elt array

    let get i a = a.(i)
end

探しているポリモーフィック バージョンよりも冗長ですが、両方の「インデックス可能な」型を均一にエンコードできます。

于 2013-01-12T01:37:13.070 に答える