comparison variant.urs @ 27:ca1c07d49b5e

Type-directed case matching for variants.
author Edward Z. Yang <ezyang@mit.edu>
date Thu, 26 Jul 2012 16:39:02 -0400
parents e7d64ea0f922
children
comparison
equal deleted inserted replaced
26:c1da0e3749b3 27:ca1c07d49b5e
41 -> r ::: {K} -> folder r -> variant (map f r) -> $(map fr r) -> t 41 -> r ::: {K} -> folder r -> variant (map f r) -> $(map fr r) -> t
42 42
43 val destr2R : K --> f1 :: (K -> Type) -> f2 :: (K -> Type) -> fr :: (K -> Type) -> t ::: Type 43 val destr2R : K --> f1 :: (K -> Type) -> f2 :: (K -> Type) -> fr :: (K -> Type) -> t ::: Type
44 -> (p :: K -> f1 p -> f2 p -> fr p -> t) 44 -> (p :: K -> f1 p -> f2 p -> fr p -> t)
45 -> r ::: {K} -> folder r -> variant (map f1 r) -> variant (map f2 r) -> $(map fr r) -> option t 45 -> r ::: {K} -> folder r -> variant (map f1 r) -> variant (map f2 r) -> $(map fr r) -> option t
46
47 (* Metaprogrammed type-directed case-match.
48
49 This uses a combination of type classes and metaprogramming to make
50 it easy to write case-matches on very large variants with many
51 similar elements. Here's how you use it:
52
53 1. For every type in the variant, write a local typeclass function
54 which reduces it to t, and register as such using the 'declareCase'
55 function in the module you created.
56
57 let val empty = declareCase (fn _ (_ : int) => True)
58
59 These functions also take an initial argument, which has
60 type [a -> variant ts]; e.g. you can use this to create
61 a new copy of the variant with different values!
62 Make sure you specify type signatures on the argument [t]
63 so that we can identify who this typeclass is for. (If you
64 use type classes to construct the return value, you may
65 also need to declare the return type explicitly.)
66
67 2. Do the match using 'typeCase':
68
69 typeCase t
70
71 If you need to override specific constructors, use this idiom:
72
73 @typeCase t (_ ++ {
74 YourConstr = declareCase (fn _ _ => ...)
75 }) _
76
77 How does it work? Very simple: it uses local typeclasses + Ur/Web's
78 support for automatically instantiating records of typeclasses.
79 *)
80
81 class type_case :: {Type} -> Type -> Type -> Type
82 val declareCase : ts ::: {Type} -> t ::: Type -> a ::: Type -> ((a -> variant ts) -> a -> t) -> type_case ts t a
83 val typeCase : ts ::: {Type} -> t ::: Type -> variant ts -> $(map (type_case ts t) ts) -> folder ts -> t