2015-09-02 5 views
1

Как мы сопоставляем матч с GADT? В этом случае у меня возникают проблемы с GADT из Bigarray. Более конкретно, кодКак сопоставить матч по GADT в Bigarray?

let print_layout v = match Bigarray.Genarray.layout v with 
    | Bigarray.C_layout -> Printf.printf "C layout\n" 
    | Bigarray.Fortran_layout -> Printf.printf "Fortran layout\n" 

не может компилировать с сообщением об ошибке

Error: This pattern matches values of type 
     Bigarray.fortran_layout Bigarray.layout 
     but a pattern was expected which matches values of type 
     Bigarray.c_layout Bigarray.layout 
     Type Bigarray.fortran_layout is not compatible with type 
     Bigarray.c_layout 

Это жалуясь о Bigarray.Fortran_layout случае. Если мы посмотрим на Bigarray мы видим, что

type c_layout = C_layout_typ 
type fortran_layout = Fortran_layout_typ 
type 'a layout = 
    C_layout : c_layout layout 
    | Fortran_layout : fortran_layout layout 

Итак, это GADT и я делаю что-то неправильно с сопоставлением с образцом. Что такое рабочая версия print_layout?

ответ

4

С помощью gadts вам часто нужно добавлять аннотации при выполнении общего шаблона (который должен работать на всех con конструкторы типа).

Вот правильный способ делать то, что вы хотите:

let print_layout (type t) (v: (_,_,t) Bigarray.Genarray.t) = 
    match Bigarray.Genarray.layout v with 
    | Bigarray.C_layout -> Printf.printf "C layout\n" 
    | Bigarray.Fortran_layout -> Printf.printf "Fortran layout\n" 

аннотации вводят абстрактный тип T, который будет типом схемы. При сопоставлении шаблонов на макете вы обнаружите, какой тип макета фактически равен.

+0

Этот синтаксис лучше, чем то, что я нашел в своих поисках :-) Спасибо! –

1

Вот функция, которая возвращает строку, представляющую расположение:

let layout_str : type l. l Bigarray.layout -> string = function 
    | Bigarray.C_layout -> "C layout" 
    | Bigarray.Fortran_layout -> "Fortran layout" 

Вы можете использовать эту функцию, чтобы определить нужную функцию

let print_layout v = 
    Printf.printf "%s\n" (layout_str (Bigarray.Genarray.layout v)) 

Это работает для меня:

$ ocaml 
     OCaml version 4.02.1 

# #load "bigarray.cma";; 
# open Bigarray;; 
# let fv = Genarray.create int32 Fortran_layout [| 0; 1; 2 |];; 
val fv : 
    (int32, Bigarray.int32_elt, Bigarray.fortran_layout) Bigarray.Genarray.t = 
    <abstr> 
# let cv = Genarray.create int32 C_layout [| 0; 1; 2 |];; 
val cv : (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Genarray.t = 
    <abstr> 
# let layout_str : type l. l Bigarray.layout -> string = function 
    | Bigarray.C_layout -> "C layout" 
    | Bigarray.Fortran_layout -> "Fortran layout";; 
val layout_str : 'l Bigarray.layout -> string = <fun> 
# let print_layout v = 
    Printf.printf "%s\n" (layout_str (Bigarray.Genarray.layout v));; 
val print_layout : ('a, 'b, 'c) Bigarray.Genarray.t -> unit = <fun> 
# print_layout fv;; 
Fortran layout 
- : unit =() 
# print_layout cv;; 
C layout 
- : unit =() 
# 

 Смежные вопросы

  • Нет связанных вопросов^_^