Skip to content

Instantly share code, notes, and snippets.

@jozefg
Last active October 8, 2015 21:51
Show Gist options
  • Save jozefg/46c59baffe37f11c6a2b to your computer and use it in GitHub Desktop.
Save jozefg/46c59baffe37f11c6a2b to your computer and use it in GitHub Desktop.
The magic of extensible types.
signature TAG =
sig
type tagged
type 'a tag
val new : unit -> 'a tag
val tag : 'a tag -> 'a -> tagged
val untag : 'a tag -> tagged -> 'a option
end
functor Tag () :> TAG =
struct
type tagged = exn
type 'a tag = { handleTag : exn -> 'a option
, makeTag : 'a -> exn
}
fun new () : 'a tag =
let
exception Tag of 'a
in
{ makeTag = Tag
, handleTag = fn e =>
(raise e) handle Tag a => SOME a | _ => NONE
}
end
fun tag {makeTag, handleTag} = makeTag
fun untag {makeTag, handleTag} = handleTag
end
(* A quick demonstration *)
local
structure Test = Tag ()
in
open Test
end
val intTag = new () : int tag
val stringTag = new () : string tag
val i = tag intTag
val s = tag stringTag
val mixed = [i 1, i 2, s "Hello World", s "Foo"]
val intsOnly = List.mapPartial (untag intTag) mixed
val stringsOnly = List.mapPartial (untag stringTag) mixed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment