@@ -1,230 +0,0 @@
1−module Heterogeneous.Extrablatt.Rec where
2−
3−import Prelude
4−import Data.Symbol (class IsSymbol)
5−import Heterogeneous.Folding (class FoldingWithIndex, class FoldlRecord, class HFoldlWithIndex, hfoldlWithIndex)
6−import Prim.Row as Row
7−import Prim.RowList (class RowToList)
8−import Record.Builder (Builder)
9−import Record.Builder as Builder
10−import Type.Proxy (Proxy)
11−
12−-- Helper for type inference
13−data HSequenceRec (f :: Type -> Type)
14− = HSequenceRec
15−
16−-- Matches if the type of the current field in the record is f a and therefore needs to be sequenced.
17−instance hsequenceRec_1 ::
18− ( Applicative f
19− , IsSymbol sym
20− , Row.Lacks sym rb
21− , Row.Cons sym a rb rc
22− ) =>
23− FoldingWithIndex
24− (HSequenceRec f)
25− (Proxy sym)
26− (f (Builder { | ra } { | rb }))
27− (f a)
28− (f (Builder { | ra } { | rc })) where
29− foldingWithIndex _ prop rin a = (>>>) <$> rin <*> (Builder.insert prop <$> a)
30−
31−-- Matches if the type of the current field in the record is another record and therefore needs to be recursed.
32−else instance hsequenceRec_2 ::
33− ( Applicative f
34− , IsSymbol sym
35− , Row.Lacks sym rb
36− , RowToList x xRL
37− , Row.Cons sym { | y } rb rc
38− , FoldlRecord
39− (HSequenceRec f)
40− (f (Builder (Record ()) (Record ())))
41− xRL
42− x
43− (f (Builder (Record ()) (Record y)))
44− ) =>
45− FoldingWithIndex
46− (HSequenceRec f)
47− (Proxy sym)
48− (f (Builder { | ra } { | rb }))
49− { | x }
50− (f (Builder { | ra } { | rc })) where
51− foldingWithIndex _ prop rin x = (>>>) <$> rin <*> (fx <#> Builder.insert prop)
52− where
53− fx = hsequenceRec x
54−
55−-- Matches if the type of the current field in the record is any other type independent of sequencing.
56−else instance hsequenceRec_3 ::
57− ( Applicative f
58− , IsSymbol sym
59− , Row.Lacks sym rb
60− , Row.Cons sym x rb rc
61− ) =>
62− FoldingWithIndex
63− (HSequenceRec f)
64− (Proxy sym)
65− (f (Builder { | ra } { | rb }))
66− x
67− (f (Builder { | ra } { | rc })) where
68− foldingWithIndex _ prop rin x = (_ >>> Builder.insert prop x) <$> rin
69−
70−-- | Recursively sequence a record. E.g.
71−-- | ```purescript
72−-- | hsequenceRec { a : { b : { c : { d: Just 10, e : Just "hello" }, f : Just true }
73−-- | -- Just { a : { b : { c : { d: 10, e : "hello" }, f : true }
74−-- | ```
75−hsequenceRec ::
76− forall f rin rout.
77− Applicative f =>
78− HFoldlWithIndex (HSequenceRec f) (f (Builder {} {})) { | rin } (f (Builder {} { | rout })) =>
79− { | rin } ->
80− f { | rout }
81−hsequenceRec =
82− map (flip Builder.build {})
83− <<< hfoldlWithIndex (HSequenceRec :: HSequenceRec f) (pure identity :: f (Builder {} {}))
84−
85−-- Helper for type inference
86−data HMapRec a b
87− = HMapRec (a -> b)
88−
89−-- Matches if the type of the current field in the record is a and therefore needs to be mapped.
90−instance hmapRec_1 ::
91− ( IsSymbol sym
92− , Row.Lacks sym rb
93− , Row.Cons sym b rb rc
94− ) =>
95− FoldingWithIndex
96− (HMapRec a b)
97− (Proxy sym)
98− (Builder { | ra } { | rb })
99− a
100− (Builder { | ra } { | rc }) where
101− foldingWithIndex (HMapRec f) prop rin a = (rin >>> Builder.insert prop (f a))
102−
103−-- Matches if the type of the current field in the record is another record and therefore needs to be recursed.
104−else instance hmapRec_2 ::
105− ( IsSymbol sym
106− , Row.Lacks sym rb
107− , RowToList x xRL
108− , Row.Cons sym { | y } rb rc
109− , FoldlRecord
110− (HMapRec a b)
111− (Builder (Record ()) (Record ()))
112− xRL
113− x
114− (Builder (Record ()) (Record y))
115− ) =>
116− FoldingWithIndex
117− (HMapRec a b)
118− (Proxy sym)
119− (Builder { | ra } { | rb })
120− { | x }
121− (Builder { | ra } { | rc }) where
122− foldingWithIndex (HMapRec f) prop rin x = (rin >>> Builder.insert prop fx)
123− where
124− fx = hmapRec f x
125−
126−-- Matches if the type of the current field in the record is any other type independent of mapping.
127−else instance hmapRec_3 ::
128− ( IsSymbol sym
129− , Row.Lacks sym rb
130− , Row.Cons sym x rb rc
131− ) =>
132− FoldingWithIndex
133− (HMapRec a b)
134− (Proxy sym)
135− (Builder { | ra } { | rb })
136− x
137− (Builder { | ra } { | rc }) where
138− foldingWithIndex _ prop rin x = (rin >>> Builder.insert prop x)
139−
140−-- | Recursively maps a record using a function f.
141−-- | ```purescript
142−-- | let
143−-- | f :: Int -> String
144−-- | f i = show (i + 1)
145−-- | hmapRec f { a : { b : 10, c : { d: 20, e : Just "hello" }}, f : 30 }
146−-- | -- { a : { b : "11", c : { d: "21", e : Just "hello" }, f : "31" }
147−-- | ```
148−hmapRec ::
149− forall a b rin rout.
150− HFoldlWithIndex (HMapRec a b) (Builder {} {}) { | rin } (Builder {} { | rout }) =>
151− (a -> b) ->
152− { | rin } ->
153− { | rout }
154−hmapRec f =
155− (flip Builder.build {})
156− <<< hfoldlWithIndex (HMapRec f :: HMapRec a b) (identity :: Builder {} {})
157−
158−-- Helper for type inference
159−data HMapKRec :: forall k. (k -> Type) -> (k -> Type) -> Type
160−data HMapKRec f g
161− = HMapKRec (f ~> g)
162−
163−-- Matches if the type of the current field in the record is f a and therefore needs to be naturally transformed.
164−instance hmapKRec_1 ::
165− ( IsSymbol sym
166− , Row.Lacks sym rb
167− , Row.Cons sym (g a) rb rc
168− ) =>
169− FoldingWithIndex
170− (HMapKRec f g)
171− (Proxy sym)
172− (Builder { | ra } { | rb })
173− (f a)
174− (Builder { | ra } { | rc }) where
175− foldingWithIndex (HMapKRec nt) prop rin fa = (rin >>> Builder.insert prop (nt fa))
176−
177−-- Matches if the type of the current field in the record is another record and therefore needs to be recursed.
178−else instance hmapKRec_2 ::
179− ( IsSymbol sym
180− , Row.Lacks sym rb
181− , RowToList x xRL
182− , Row.Cons sym { | y } rb rc
183− , FoldlRecord
184− (HMapKRec f g)
185− (Builder (Record ()) (Record ()))
186− xRL
187− x
188− (Builder (Record ()) (Record y))
189− ) =>
190− FoldingWithIndex
191− (HMapKRec f g)
192− (Proxy sym)
193− (Builder { | ra } { | rb })
194− { | x }
195− (Builder { | ra } { | rc }) where
196− foldingWithIndex (HMapKRec nt) prop rin x = (rin >>> Builder.insert prop fx)
197− where
198− fx = hmapKRec nt x
199−
200−-- Matches if the type of the current field in the record is any other type independent of the natural transformation.
201−else instance hmapKRec_3 ::
202− ( IsSymbol sym
203− , Row.Lacks sym rb
204− , Row.Cons sym x rb rc
205− ) =>
206− FoldingWithIndex
207− (HMapKRec f g)
208− (Proxy sym)
209− (Builder { | ra } { | rb })
210− x
211− (Builder { | ra } { | rc }) where
212− foldingWithIndex _ prop rin x = (rin >>> Builder.insert prop x)
213−
214−-- | Recursively mapK a record using a natural transformation. E.g.
215−-- | ```purescript
216−-- | let
217−-- | nt :: Either String ~> Maybe
218−-- | nt = hush
219−-- | hmapKRec { a : { b : { c : { d: Right 10, e : Left "hello" }, f : Right true }
220−-- | -- Just { a : { b : { c : { d: Just 10, e : Nothing }, f : Just true }
221−-- | ```
222−hmapKRec ::
223− forall f g rin rout.
224− HFoldlWithIndex (HMapKRec f g) (Builder {} {}) { | rin } (Builder {} { | rout }) =>
225− (f ~> g) ->
226− { | rin } ->
227− { | rout }
228−hmapKRec nt =
229− (flip Builder.build {})
230− <<< hfoldlWithIndex (HMapKRec nt :: HMapKRec f g) (identity :: Builder {} {})