caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Rodolphe Lepigre <rodolphe.lepigre@univ-savoie.fr>
To: Trevor Smith <trevorsummerssmith@gmail.com>
Cc: "caml-list@inria.fr" <caml-list@inria.fr>
Subject: Re: [Caml-list] GADTs and JSON
Date: Thu, 21 May 2015 20:44:04 +0200	[thread overview]
Message-ID: <20150521184404.GA598@HPArchRod> (raw)
In-Reply-To: <CAG-KTt_Um5B263zK3M6Y7on62-F0rrkb-1MpcRtMqTH6tLRDjQ@mail.gmail.com>

Hi,

> Is it possible to encode a recursive, heterogenous map and list datastructure
> with GADTs?
> 
> I want to encode JSON (there are already a couple of great libraries out there
> so this is kind of an academic question). I would like to have functions that
> can only take a JSON map type, for example to take a json map and return a
> value. The key here is that the map can hold values of type int,string and also
> maps. Is this possible?
> 
> eg get : (map : map json) -> key:string -> 'a json
> 
> Thank you.
> 
> Trevor

You should probably have a look at the examples given for GADTs on the page
about language extensions (advanced examples section):

http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc85

Not so long ago I used equality types to encode collections of object of
different types. Here is an example with lists and a function for obtaining
the n-th element.

##########
type (_,_) eq = Eq : ('a,'a) eq

type 'a typ =
  | Int   : int typ
  | Float : float typ
  | Pair  : 'a typ * 'b typ -> ('a * 'b) typ

let rec equal : type a b. a typ -> b typ -> (a,b) eq option = fun t1 t2 ->
  match (t1,t2) with
  | (Int       , Int      ) -> Some Eq
  | (Float     , Float    ) -> Some Eq
  | (Pair(a,b) , Pair(c,d)) ->
      begin
        match (equal a c, equal b d) with
        | (Some Eq, Some Eq)  -> Some Eq 
        | _                   -> None
      end
  | _                       -> None

type _ tlist' =
  | Nil  : unit tlist'
  | Cons : ('a typ * 'a * unit tlist') -> unit tlist'

type tlist = unit tlist'

let rec nth : type a. tlist -> int -> a typ -> a = fun l n ty ->
  match (l, n) with
  | (Nil          , _) -> raise Not_found
  | (Cons(ty',t,_), 0) ->
      begin
        match equal ty ty' with
        | Some Eq -> t
        | None    -> invalid_arg "Ill type in nth"
      end
  | (Cons(_,_,l)  , _) -> nth l (n-1) ty

let l = Cons(Int, 3, Cons(Float, 4.2, Nil))

let n : int   = nth l 0 Int
let f : float = nth l 1 Float
##########

Regards,

Rodolphe

-- 
Rodolphe Lepigre
LAMA, Université de Savoie, FRANCE
http://lama.univ-savoie.fr/~lepigre/

      parent reply	other threads:[~2015-05-21 18:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-21 16:42 Trevor Smith
2015-05-21 16:59 ` Milan Stanojević
2015-05-21 18:44 ` Rodolphe Lepigre [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150521184404.GA598@HPArchRod \
    --to=rodolphe.lepigre@univ-savoie.fr \
    --cc=caml-list@inria.fr \
    --cc=trevorsummerssmith@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).