Как да разопаковам накратко алгебричен тип данни в OCaml?

Има ли добър начин за кратко разгръщане на алгебричен тип данни в OCaml? Например, разгледайте следния код, който дефинира два различни типа математически функции

type ftype =                                                         
    | Quadratic of {alpha : float; a : float array; aa : float array}
    | General of {eval : float array->float}
type myfn = {                                                                   
    nvar : int;
    typ : ftype}  
let f = {                                                                       
    nvar = 2;                                                                   
    typ = General {eval = fun x-> x.(0) +. x.(1)}} 

За целите на отстраняването на грешки понякога е хубаво просто да оцените функция или да проверите нейните стойности в най-високото ниво. Въпреки това, ако искаме да оценим f, се нуждаем от код, който изглежда като

let x = [| 1.; 2. |]
let y = match f.typ with General(f) -> f.eval(x)

Това е някак грозно и е болезнено за писане, особено ако наслояването е дълбоко няколко слоя. Бих искал да дефинирам някакъв синтаксис като

let y = f.typ.General.eval(x)

И, да, кодът не е безопасен и това няма да се компилира. Въпреки това, нещо близко до това би било хубаво за целите на отстраняване на грешки, така че да не се налага да пишем дълъг код, за да разопаковаме стойност. Има ли добър начин да се постигне това?


person wyer33    schedule 16.08.2018    source източник
comment
Можете да деструктурирате с let binding: let y = let { typ = General(f) } = f in f.eval(x). Вероятно по-малко грозен, но със сигурност не по-къс в този случай. Въпреки това ще се справи по-добре с гнезденето.   -  person glennsl    schedule 17.08.2018


Отговори (2)


Ако е само за отстраняване на грешки, винаги можете да напишете:

let { typ = General { eval; } ; } = f in
let y = eval x in
...

Разбира се, компилаторът ще ви отпечата предупреждение 8 (неизчерпателно съвпадение на шаблон).

Не мисля, че можете да направите по-сбито, типовете суми са предназначени да бъдат четливи и безопасни. Не бързам, съжалявам.

person PatJ    schedule 17.08.2018

Когато играете с кода си на най-високото ниво, е напълно добре да използвате опровержими (т.е. непълни) модели, напр.

let [1;3;5] = List.filter is_odd [1;2;3;4;5]

За да предотвратите развалянето на горното ниво с предупреждения, просто ги деактивирайте с

#warnings "-P";;

(или "-8", това е същото и не забравяйте да въведете водещото #, това е част от директивата, а не подканата).

person ivg    schedule 17.08.2018