如何在数组和字符串上编写仿函数?

rgr*_*erg 3 ocaml

我想使用以下签名使我的代码在字符串和数组(真正的任何可索引类型)上通用:

module type Indexable = sig
  type 'a t
  val get : int -> 'a t -> 'a
end
Run Code Online (Sandbox Code Playgroud)

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

但是我当然不能将我的签名应用于字符串,如下所示:

module StrMyCode = MyCode(struct
  type 'a t = string
  let get i a = a.[i]
end)
Run Code Online (Sandbox Code Playgroud)

有什么方法可以解决这个问题吗?或者也许是另一种不同的方式?我知道在最糟糕的情况下我可以使用字符数组,但我宁愿将代码保存在丑陋的演员表中,这是我之前想到的,所以我想得到一个明确的答案.

Vir*_*ile 6

GADT可以与funorized方法一起使用:

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
Run Code Online (Sandbox Code Playgroud)

数组当然可以是Indexable平凡的:

module IndexableArray = struct
  type 'a t = 'a array
  let get i x = x.(i)
end
Run Code Online (Sandbox Code Playgroud)

对于字符串,您可以使用具有单个构造函数的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
Run Code Online (Sandbox Code Playgroud)


Jef*_*eld 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)
Run Code Online (Sandbox Code Playgroud)

如果我加载到顶层,我得到这个:

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

这可能不像你想要的那样一般.