Just like there exists a programming languages zoo, nested datatype pets merit their own mini-zoo.
I propose a simple minimal signature :
module type Datatype =
sig
type 'a t
val map : ('a -> 'b) -> 'a t -> 'b t
val size : 'a t -> int
type index
val member : index -> 'a t -> 'a
end
The first mentioned nested datatype is 'a Nest.t
:
(* a nested datatype from the paper "Nested Datatypes"
* by Richard Bird and Lambert Meertens 1998
* size & member are implemented by Chris Okasaki
*)
module Nest
=
struct
type 'a t =
| Nil
| Cons of 'a * ('a * 'a) t
let pair_map f (x,y) =
(f x,f y)
let rec map : 'a 'b . ('a -> 'b) -> 'a t -> 'b t =
fun f -> function
| Nil -> Nil
| Cons(h,t) -> Cons(f h,map (pair_map f) t)
let rec size : 'a . 'a t -> int = function
| Nil -> 0
| Cons(_,t) -> 1 + 2 * size t
type index =
int
let rec member : 'a . index -> 'a t -> 'a =
fun n -> function
| Nil -> failwith "Nest.member"
| Cons(h,t) ->
if n=0 then h else
let x,y = member (n/2) t in
if n mod 2 = 0 then x else y
end
The next is the incomplete 'a Bush.t
:
(* another nested datatype from the paper "Nested Datatypes"
* by Richard Bird and Lambert Meertens 1998
* i don't see how to implement size & member
*)
module Bush
=
struct
type 'a t =
| Nil
| Cons of 'a * 'a t t
let rec map : 'a 'b . ('a -> 'b) -> 'a t -> 'b t =
fun f -> function
| Nil -> Nil
| Cons(h, t) -> Cons(f h,map (map f) t)
let rec size : 'a . 'a t -> int = function
| _ -> assert false
type index =
unit (* i don't even see what the index type should be *)
let rec member : 'a . index -> 'a t -> 'a = function
| _ -> assert false
end
The last known to me is the incomplete 'a Lush.t
:
(* the last nested datatype known to me
* i don't see how to implement size without to_list
* i don't see how to fully implement member
*)
module Lush
=
struct
type 'a t =
| Item of 'a
| List of 'a list t
let rec map : 'a 'b. ('a -> 'b) -> 'a t -> 'b t =
fun f -> function
| Item x -> Item (f x)
| List l -> List (map (List.map f) l)
let rec to_list : 'a. 'a t -> 'a list = function
| Item x -> [x]
| List l -> List.concat (to_list l);;
let size t =
List.length (to_list t)
type index =
int list
let member =
fun (i:index) t ->
match i,t with
| _,Item _ -> assert false
| [a],List(Item l) -> List.nth l a
| [a;b],List(List(Item l)) -> List.nth (List.nth l a) b
end
Can you help me to complete the zoo with size
& member
functions and/or an innovative new nested datatype ?
Thank for your effort.