Diciamo che ho una lista di opzioni:OCaml: più alto il polimorfismo kinded (astrazione su moduli?)
let opts = [Some 1; None; Some 4]
mi piacerebbe convertirli in un'opzione di lista, in modo tale che:
- Se l'elenco contiene
None
, il risultato èNone
- In caso contrario, i vari int sono raccolti.
E 'relativamente semplice di scrivere questo per questo caso specifico (utilizzando Core e il modulo Monad
):
let sequence foo =
let open Option in
let open Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
Tuttavia, come suggerisce il titolo della domanda, mi piacerebbe davvero astratta sopra il tipo costruttore piuttosto che specializzarsi a Option
. Il core sembra utilizzare un funtore per dare l'effetto di un tipo più alto, ma non sono chiaro in che modo posso scrivere la funzione da astrarre sul modulo. In Scala, utilizzerei un contesto implicito per richiedere la disponibilità di alcuni Monad[M[_]]
. Mi aspetto che non ci sia modo di passare implicitamente nel modulo, ma come lo farei esplicitamente? In altre parole, posso scrivere qualcosa di simile a questo:
let sequence (module M : Monad.S) foo =
let open M in
let open M.Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
È qualcosa che può essere fatto con moduli di prima classe?
Modifica: Ok, quindi non mi è venuto in mente di provare a utilizzare quel codice specifico, e sembra che sia più vicino al lavoro di quanto mi aspettassi! Sembra la sintassi è infatti valida, ma ottengo questo risultato:
Error: This expression has type 'a M.t but an expression was expected of type 'a M.t
The type constructor M.t would escape its scope
La prima parte del errore sembra confusa, in quanto essi corrispondono, quindi sto cercando di indovinare il problema è con il secondo - è il problema qui che il tipo di ritorno non sembra essere determinato? Suppongo che dipenda dal modulo che è passato - è un problema? C'è un modo per risolvere questa implementazione?
Questa vecchia domanda potrebbe esserti utile: http://stackoverflow.com/questions/1986374/higher-order-type-constructors-and-functors-in-ocaml – rgrinberg