|
| 1 | +local import "prelude" |
| 2 | + |
| 3 | +;; As 1ML is powerful enough to encode GADTs we can define a value independent |
| 4 | +;; type representation or a deep embedding of type constructors. |
| 5 | + |
| 6 | +type iso a b = {to: a ~> b, from: b ~> a} |
| 7 | + |
| 8 | +Rep = { |
| 9 | + data case t _ :> { |
| 10 | + bool: case bool |
| 11 | + char: case char |
| 12 | + int : case int |
| 13 | + text: case text |
| 14 | + unit: case unit |
| 15 | + |
| 16 | + alt 'x 'y: t x ~> t y ~> case (alt x y) |
| 17 | + ~~> 'x 'y: t x ~> t y ~> case (x ~> y) |
| 18 | + pair 'x 'y: t x ~> t y ~> case (x, y) |
| 19 | + |
| 20 | + iso 'x 'y: iso x y ~> t y ~> case x |
| 21 | + |
| 22 | + lazy 'x: ({} ~> t x) ~> case x |
| 23 | + } |
| 24 | + |
| 25 | + defaults (type t _) (default 'a: t a) = { |
| 26 | + bool = default |
| 27 | + char = default |
| 28 | + int = default |
| 29 | + unit = default |
| 30 | + text = default |
| 31 | + |
| 32 | + alt _ _ = default |
| 33 | + _ ~~> _ = default |
| 34 | + pair _ _ = default |
| 35 | + |
| 36 | + iso _ _ = default |
| 37 | + |
| 38 | + lazy _ = default |
| 39 | + } |
| 40 | + |
| 41 | + local i = {to = Opt.case {none = inl {}, some = inr} |
| 42 | + from = Alt.case {inl {} = none, inr = some}} |
| 43 | + opt a = iso i (alt unit a) |
| 44 | + |
| 45 | + local i = {to = List.case {nil = inl {}, x :: xs = inr (x, xs)} |
| 46 | + from = Alt.case {inl {} = nil, inr (x, xs) = x::xs}} |
| 47 | + list v = rec vs => lazy fun {} => iso i (alt unit (pair v vs)) |
| 48 | +} |
| 49 | + |
| 50 | +;; Generic toText |
| 51 | + |
| 52 | +ToText = {type t x = x ~> text} |
| 53 | + |
| 54 | +toText = rec (toText 'x: Rep.t x ~> ToText.t x) => Rep.case ToText.t { |
| 55 | + bool = Bool.toText |
| 56 | + char c = "'" ++ Text.fromChar c ++ "'" |
| 57 | + int = Int.toText |
| 58 | + text t = "\"" ++ t ++ "\"" |
| 59 | + unit {} = "{}" |
| 60 | + |
| 61 | + alt aT bT = Alt.case { |
| 62 | + inl a = "(inl " ++ toText aT a ++ ")" |
| 63 | + inr b = "(inr " ++ toText bT b ++ ")" |
| 64 | + } |
| 65 | + |
| 66 | + (_ ~~> _) _ = "<fun>" |
| 67 | + |
| 68 | + pair aT bT (a, b) = "(" ++ toText aT a ++ ", " ++ toText bT b ++ ")" |
| 69 | + |
| 70 | + iso ab bT = ab.to >> toText bT |
| 71 | + |
| 72 | + lazy th = toText (th {}) |
| 73 | +} |
| 74 | + |
| 75 | +println rep x = print (toText rep x ++ "\n") |
| 76 | + |
| 77 | +do let ...Rep |
| 78 | + println int 101 |
| 79 | + println (pair bool text) (true, "that") |
| 80 | + println (opt bool) (some false) |
| 81 | + println (iso {to i = i <> 0, from b = if b then 1 else 0} bool) 1 |
| 82 | + println (list int) (3 :: (1 :: (4 :: nil))) |
| 83 | + |
| 84 | +;; Generic eq |
| 85 | + |
| 86 | +Eq = {type t x = x ~> x ~> bool} |
| 87 | + |
| 88 | +eq = rec (eq 'x: Rep.t x ~> Eq.t x) => Rep.case Eq.t { |
| 89 | + bool = Bool.== |
| 90 | + char = Char.== |
| 91 | + int = Int.== |
| 92 | + text = Text.== |
| 93 | + unit _ _ = true |
| 94 | + |
| 95 | + alt aT bT l r = l |> Alt.case { |
| 96 | + inl l = r |> Alt.case {inl = eq aT l, inr _ = false} |
| 97 | + inr l = r |> Alt.case {inl _ = false, inr = eq bT l} |
| 98 | + } |
| 99 | + |
| 100 | + (_ ~~> _) _ _ = false |
| 101 | + |
| 102 | + pair aT bT (l1, l2) (r1, r2) = eq aT l1 r1 && eq bT l2 r2 |
| 103 | + |
| 104 | + iso ab bT l r = eq bT (ab.to l) (ab.to r) |
| 105 | + |
| 106 | + lazy th l r = eq (th {}) l r |
| 107 | +} |
| 108 | + |
| 109 | +do let ...Rep |
| 110 | + test t l r = print ("eq " ++ toText t l ++ |
| 111 | + " " ++ toText t r ++ |
| 112 | + " = " ++ toText bool (eq t l r) ++ "\n") |
| 113 | + test int 101 42 |
| 114 | + test (pair int bool) (1, true) (1, true) |
| 115 | + test (list int) (3 :: (1 :: nil)) (4 :: (1 :: nil)) |
| 116 | + test (list int) (4 :: (2 :: nil)) (4 :: (2 :: nil)) |
0 commit comments