2013-01-12 1 views
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) 

이 문제를 해결할 방법이 있습니까? 아니면 다른 aprroach일까요? 나는 최악의 경우에 문자 배열을 사용할 수 있다는 것을 알고 있지만 추악한 캐스트에서 코드를 저장하고 싶습니다. 그리고 이것은 내 마음 속에 있었던 무언가이기 때문에 이에 대한 명확한 답을 얻고 싶습니다.

답변

5

다음은 GADT를 사용하여 만든 것입니다. 나는 그들 주위에 머리를 감쌀 뿐이므로 여기에 약간 잘못된 것이있을 수 있습니다.

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

이는 것과 같은 일반적인되지 않을 수도 있습니다 : 나는 최상위에로드하면

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) 

, 나는이 얻을 :하지만 내가 (OCaml의 4) 볼 수까지 작동하는 것 같다 너 찾고있어. 별도의 유형으로 색인의 요소 유형을 선언하면

+1

나중에이 영리한 솔루션입니다하지만 난 펑터 접근 방식을 취하고 : 당신이 다형성 유형을 강제하기 위해 GET에 대한 어떤 종류의 주석을 넣어 가지고, 그러나 주 (그렇지 않으면 추론 유형은 int -> char t -> char입니다) 왜냐하면 사용자가 자신의 인덱스 테이블을 구현할 수 있기를 바랍니다. – rgrinberg

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 

찾고있는 다형성 버전보다 자세한 정보를 제공하지만 "인덱싱 가능"유형을 모두 일률적으로 인코딩 할 수 있습니다.

+0

배열에 대해 Indexable을 구현하는 방법은'type t = '배열'이 typecheck되지 않습니다. 또한 이것이 작동하더라도 컨테이너의 파라 메트릭 다형성을 여전히 잃어 버릴 것이라고 생각합니다. 예를 들어'int array'와'string array'에 대해 펑터를 개별적으로 인스턴스화해야합니다. 아마도 내가 요구하는 것은 비록 인스턴스화 된 펑터를 1 개의 경우 : 문자열을 제외한 컨테이너의 값에 대해 다형성을 유지하고 싶기 때문에 의미가 없습니다. 내가 입력 한 내용이 지금도 의미가 있는지조차 모르겠다. – rgrinberg

+1

네, 요소 유형에 대해 파라 메트릭 다형성을 유지할 수있는 방법을 생각할 수 없습니다. –

6

GADT는 functorized 접근 방식과 함께 사용할 수 있습니다

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를 사용할 수 있습니다.

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 
관련 문제