4 | import public Data.List.Fresh
5 | import public Data.List.Fresh.Quantifiers
8 | import public Decidable.Decidable.Extra1
9 | import public Decidable.Equality
11 | %hide Builtin.infixr.(#)
17 | ArgList = FreshList String String.(##)
20 | Field : (String -> Type) -> Type
21 | Field a = (nm : String ** a nm)
24 | Fields : (String -> Type) -> Type
25 | Fields a = FreshList (Field a) ((##) `on` fst)
28 | record Record {0 A : String -> Type}
29 | (0 F : Field A -> Type)
30 | (0 Flds : Fields A) where
31 | constructor MkRecord
32 | content : All F Flds
37 | map : {flds : Fields a} -> ((x : Field a) -> f x -> g x) ->
38 | Record f flds -> Record g flds
39 | map f (MkRecord rec) = MkRecord (All.map f rec)
42 | IsField : (fldName : String) -> (flds : Fields a) -> Type
43 | IsField fldName flds = Any (\ u => fldName === fst u) flds
46 | isYesBecause : (d : Dec p) -> p -> IsYes d
47 | isYesBecause (Yes prf) p = ItIsYes
48 | isYesBecause (No nprf) p = absurd (nprf p)
52 | soNotToEq : {b : Bool} -> So (not b) -> b = False
53 | soNotToEq {b = False} Oh = Refl
56 | stringEq : {x, y : String} -> x === y -> (x == y) === True
57 | stringEq eq = go (decEq x y `isYesBecause` eq) where
59 | go : IsYes (decEq x y) -> (x == y) === True
64 | IsFieldStale : nm `IsField` flds -> fst nmv === nm ->
65 | (0 fresh : nmv # flds) -> Void
66 | IsFieldStale (Here Refl) eq fresh
67 | = absurd $
trans (sym $
stringEq eq) (soNotToEq $
fst $
soAnd fresh)
68 | IsFieldStale (There pos) eq fresh
69 | = IsFieldStale pos eq (snd $
soAnd fresh)
72 | IsFieldIrrelevant : (p, q : nm `IsField` flds) -> p === q
73 | IsFieldIrrelevant (Here Refl) (Here Refl) = Refl
74 | IsFieldIrrelevant (Here Refl) (There {fresh} p)
75 | = void $
IsFieldStale p Refl fresh
76 | IsFieldIrrelevant (There {fresh} p) (Here Refl)
77 | = void $
IsFieldStale p Refl fresh
78 | IsFieldIrrelevant (There p) (There q)
79 | = cong There (IsFieldIrrelevant p q)
82 | isField : (fldName : String) -> (flds : Fields a) ->
83 | Dec (fldName `IsField` flds)
84 | isField fldName flds = any (\u => decEq fldName (fst u)) flds
87 | field : {flds : Fields a} -> (pos : Any p flds) -> Field a
88 | field pos = lookup pos
91 | (.project) : {flds : Fields a} -> (rec : Record f flds) -> (name : String) ->
92 | {auto pos : IsYes $
name `isField` flds} -> f (field $
toWitness pos)
93 | rec.project name = rec.content !! _
98 | (f : (arg : String) -> Any (arg ===) args -> a arg) ->
102 | 0 tabulateFreshness : {0 a : String -> Type} -> (args : ArgList) ->
103 | (f : (arg : String) -> Any (arg ===) args -> a arg) ->
104 | {0 y : String} -> {0 u : a y} ->
105 | (y # args) -> (
y ** u)
# tabulate args f
108 | tabulate ((x :: xs) {fresh}) f
109 | = ((
x ** f x (Here Refl))
:: tabulate xs (\u, pos => f u $
There pos))
110 | {fresh = tabulateFreshness xs _ fresh}
112 | tabulateFreshness [] f fresh = Oh
113 | tabulateFreshness (x :: xs) f fresh
114 | = let (y_fresh_x, y_fresh_xs) = soAnd fresh in
115 | andSo (y_fresh_x, tabulateFreshness xs _ y_fresh_xs)
118 | map : (f : (nm : String) -> a nm -> b nm) -> Fields a -> Fields b
119 | map f = Data.List.Fresh.map
120 | (\ (
nm ** a)
=> (
nm ** f nm a)
)
121 | (\(_**_), (_**_) => id)
124 | foldl : (f : b -> a -> b) -> b -> Record (const a) flds -> b
125 | foldl f x = foldl f x . content
128 | TypeFields : {flds : Fields a} ->
129 | (rec : Record (const Type) flds ) -> Fields (const Type)
130 | TypeFields rec = Fresh.map (\ ((nm ** _) ** ty) => (
nm ** ty)
)
131 | (\((_**_) ** _),((_**_) ** _) => id)
132 | (rec.content.toFreshList)
135 | PartialRecord : (f : Field a -> Type) -> Fields a -> Type
136 | PartialRecord f flds = Record (Maybe . f) flds
139 | traverse : {flds : Fields a} ->
141 | ((x : Field a) -> f x -> m (g x)) ->
142 | Record f flds -> m (Record g flds)
143 | traverse f rec = MkRecord <$> (Quantifiers.traverse f rec.content)
146 | sequence : Applicative g =>
147 | Record (g . f) flds -> g (Record f flds)
148 | sequence rec = MkRecord <$> (Quantifiers.sequence rec.content)