ocaml runtime type information
Nov. 28th, 2011 05:21 pmКак некоторые знают, я некоторое время занимаюсь способами привнести немного runtime type information в окамловские строго- и статически- типизированные программы.
Репка -- https://bitbucket.org/gds/cadastr/src
Как один из примеров:
Тут мы определяем информацию о типе "список". Что же тут необычного:
1. не создаём никакого описания типа, наподобие [Nil | Cons of ..], вместо этого указываем просто "тип -- как бы sum type, который можно разрушить так-то", однако, на вход пойдёт именно list 'a, классический.
2. переопределяем сравнение так, чтобы, независимо от имён конструкторов (List.{nil,cons}), сравнение шло так, чтобы пустой список (nil) был всегда меньше cons-ячейки списка.
3. указываем, что, несмотря на имена конструкторов и sum type, список надо показывать в виде "[elem1; elem2; ...; elemN]", а не как нормальные sum types по умолчанию, "List.cons elem1 (List.cons elem2 List.nil)" (в случае, если пользователь new List.ti ti_elem не переопределил show так, как ему вздумается, через опциональный аргумент ?show:(list 'a -> string)).
Репка -- https://bitbucket.org/gds/cadastr/src
Как один из примеров:
module List =
...
class ti ['z]
?cmp ?eq ?hash ?show
(ti_elem : #Cdt.ti 'b)
() =
object (self : #tifull (list 'a))
constraint 'z = list 'a;
inherit Cdt.ti ['z] ();
method type_desc = ti_dispatch (
let proc vnil vcons = Sum_type (fun ub ->
match (uget_exn self ub) with
[ [] -> ti_variant vnil [| |]
| [h :: t] -> ti_variant vcons [| ubox ti_elem h ; ubox self t |]
])
in fun
[ "cmp" -> proc "List.0" "List.1"
| _ -> proc "List.nil" "List.cons"
]
)
;
inherit tifull_ops [_] ?cmp ?eq ?hash
~show:
(match show with
[ None ->
fun lst ->
dump
~begins:"[" ~ends:"]" ~delim:"; "
ti_elem
lst
| Some show -> show
]
)
()
;
end
;
...
Тут мы определяем информацию о типе "список". Что же тут необычного:
1. не создаём никакого описания типа, наподобие [Nil | Cons of ..], вместо этого указываем просто "тип -- как бы sum type, который можно разрушить так-то", однако, на вход пойдёт именно list 'a, классический.
2. переопределяем сравнение так, чтобы, независимо от имён конструкторов (List.{nil,cons}), сравнение шло так, чтобы пустой список (nil) был всегда меньше cons-ячейки списка.
3. указываем, что, несмотря на имена конструкторов и sum type, список надо показывать в виде "[elem1; elem2; ...; elemN]", а не как нормальные sum types по умолчанию, "List.cons elem1 (List.cons elem2 List.nil)" (в случае, если пользователь new List.ti ti_elem не переопределил show так, как ему вздумается, через опциональный аргумент ?show:(list 'a -> string)).