variant.urs 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. (** Derived functions dealing with polymorphic variants *)
  2. val read : r ::: {Unit} -> t ::: Type -> folder r -> $(mapU t r) -> variant (mapU {} r) -> t
  3. val write : r ::: {Unit} -> t ::: Type -> folder r -> $(mapU t r) -> variant (mapU {} r) -> t -> $(mapU t r)
  4. val search : r ::: {Unit} -> t ::: Type -> (variant (mapU {} r) -> option t) -> folder r -> option t
  5. val find : r ::: {Unit} -> (variant (mapU {} r) -> bool) -> folder r -> option (variant (mapU {} r))
  6. val test : nm :: Name -> t ::: Type -> ts ::: {Type} -> [[nm] ~ ts] => folder ([nm = t] ++ ts)
  7. -> variant ([nm = t] ++ ts) -> option t
  8. val testLess : nm :: Name -> t ::: Type -> ts ::: {Type} -> [[nm] ~ ts] => folder ts -> variant ([nm = t] ++ ts) -> option t
  9. val weaken : r1 ::: {Type} -> r2 ::: {Type} -> [r1 ~ r2] => folder r1
  10. -> variant r1 -> variant (r1 ++ r2)
  11. val testEq : K --> f :: (K -> Type) -> nm :: Name -> t ::: K -> ts ::: {K} -> r ::: {K} -> [[nm] ~ ts] =>
  12. Eq.eq r ([nm = t] ++ ts)
  13. -> folder r
  14. -> variant (map f r) -> option (f t)
  15. val eq : r ::: {Unit} -> folder r -> variant (mapU {} r) -> variant (mapU {} r) -> bool
  16. val makeEq : K --> f :: (K -> Type) -> nm :: Name -> t ::: K -> ts ::: {K} -> r ::: {K} -> [[nm] ~ ts] =>
  17. Eq.eq r ([nm = t] ++ ts)
  18. -> f t
  19. -> variant (map f r)
  20. val mp : r ::: {Unit} -> t ::: Type -> folder r -> (variant (mapU {} r) -> t) -> $(mapU t r)
  21. val fold : r ::: {Unit} -> t ::: Type -> folder r -> (variant (mapU {} r) -> t -> t) -> t -> t
  22. val foldR : tr ::: Type -> r ::: {Unit} -> t ::: Type -> folder r -> (variant (mapU {} r) -> tr -> t -> t) -> $(mapU tr r) -> t -> t
  23. val appR : m ::: (Type -> Type) -> monad m
  24. -> tr ::: Type -> r ::: {Unit} -> folder r -> (variant (mapU {} r) -> tr -> m {}) -> $(mapU tr r) -> m {}
  25. val mapR : tr ::: Type -> t ::: Type -> r ::: {Unit} -> folder r -> (variant (mapU {} r) -> tr -> t) -> $(mapU tr r) -> $(mapU t r)
  26. val destrR : K --> f :: (K -> Type) -> fr :: (K -> Type) -> t ::: Type
  27. -> (p :: K -> f p -> fr p -> t)
  28. -> r ::: {K} -> folder r -> variant (map f r) -> $(map fr r) -> t
  29. val destr2R : K --> f1 :: (K -> Type) -> f2 :: (K -> Type) -> fr :: (K -> Type) -> t ::: Type
  30. -> (p :: K -> f1 p -> f2 p -> fr p -> t)
  31. -> r ::: {K} -> folder r -> variant (map f1 r) -> variant (map f2 r) -> $(map fr r) -> option t
  32. (* Metaprogrammed type-directed case-match.
  33. This uses a combination of type classes and metaprogramming to make
  34. it easy to write case-matches on very large variants with many
  35. similar elements. Here's how you use it:
  36. 1. For every type in the variant, write a local typeclass function
  37. which reduces it to t, and register as such using the 'declareCase'
  38. function in the module you created.
  39. let val empty = declareCase (fn _ (_ : int) => True)
  40. These functions also take an initial argument, which has
  41. type [a -> variant ts]; e.g. you can use this to create
  42. a new copy of the variant with different values!
  43. Make sure you specify type signatures on the argument [t]
  44. so that we can identify who this typeclass is for. (If you
  45. use type classes to construct the return value, you may
  46. also need to declare the return type explicitly.)
  47. 2. Do the match using 'typeCase':
  48. typeCase t
  49. If you need to override specific constructors, use this idiom:
  50. @typeCase t (_ ++ {
  51. YourConstr = declareCase (fn _ _ => ...)
  52. }) _
  53. How does it work? Very simple: it uses local typeclasses + Ur/Web's
  54. support for automatically instantiating records of typeclasses.
  55. *)
  56. class type_case :: {Type} -> Type -> Type -> Type
  57. val declareCase : ts ::: {Type} -> t ::: Type -> a ::: Type -> ((a -> variant ts) -> a -> t) -> type_case ts t a
  58. val typeCase : ts ::: {Type} -> t ::: Type -> variant ts -> $(map (type_case ts t) ts) -> folder ts -> t