10 | module Control.DivideAndConquer
14 | namespace Section4Sub1
17 | data ListF : (a, x : Type) -> Type where
19 | (::) : a -> x -> ListF a x
21 | lengthAlg : ListF a Nat -> Nat
23 | lengthAlg (_ :: n) = S n
26 | Functor (ListF a) where
28 | map f (x :: xs) = x :: f xs
30 | namespace Section6Sub1
34 | data Mu : (Type -> Type) -> Type where
35 | MkMu : forall r. (r -> Mu f) -> f r -> Mu f
38 | inMu : f (Mu f) -> Mu f
42 | outMu : Functor f => Mu f -> f (Mu f)
43 | outMu (MkMu f d) = f <$> d
46 | fold : Functor f => (f a -> a) -> Mu f -> a
47 | fold alg (MkMu f r) = alg (assert_total (fold alg . f <$> r))
49 | namespace Section4Sub1
59 | (::) : a -> list a -> list a
60 | x :: xs = inMu (x :: xs)
62 | fromList : List a -> list a
63 | fromList = foldr (::) []
65 | toList : list a -> List a
66 | toList = fold $
\case
68 | (x :: xs) => x :: xs
70 | namespace Section4Sub2
74 | KAlg = (Type -> Type) -> Type
77 | 0 Mono : (KAlg -> KAlg) -> Type
80 | (forall x. a x -> b x) ->
81 | (forall x. f a x -> f b x)
84 | data Mu : (KAlg -> KAlg) -> KAlg where
85 | MkMu : (forall x. a x -> Mu f x) ->
86 | (forall x. f a x -> Mu f x)
89 | inMu : f (Mu f) x -> Mu f x
93 | outMu : Mono f -> Mu f x -> f (Mu f) x
94 | outMu m (MkMu f d) = m f d
96 | parameters (0 f : Type -> Type)
99 | 0 FoldT : KAlg -> Type -> Type
106 | 0 SAlgF : KAlg -> (Type -> Type) -> Type
117 | 0 SAlg : (Type -> Type) -> Type
121 | 0 AlgF : KAlg -> (Type -> Type) -> Type
130 | 0 Alg : (Type -> Type) -> Type
134 | inSAlg : SAlgF SAlg x -> SAlg x
138 | monoSAlgF : Mono SAlgF
139 | monoSAlgF f salg up sfo = salg up (sfo . f)
142 | outSAlg : SAlg x -> SAlgF SAlg x
143 | outSAlg = outMu monoSAlgF
146 | inAlg : AlgF Alg x -> Alg x
150 | monoAlgF : Mono AlgF
151 | monoAlgF f alg fo = alg (fo . f)
154 | outAlg : Alg x -> AlgF Alg x
155 | outAlg = outMu monoAlgF
157 | namespace Section6Sub2
159 | parameters (0 f : Type -> Type)
162 | 0 DcF : Type -> Type
163 | DcF a = forall x. Functor x => Alg f x -> x a
166 | functorDcF : Functor DcF
167 | functorDcF = MkFunctor $
\ f, dc, alg => map f (dc alg)
174 | fold : FoldT f (Alg f) Dc
175 | fold alg dc = outMu @{functorDcF} dc alg
178 | record RevealT (x : Type -> Type) (r : Type) where
179 | constructor MkRevealT
180 | runRevealT : (r -> Dc) -> x Dc
182 | public export %hint
183 | functorRevealT : Functor (RevealT x)
184 | functorRevealT = MkFunctor $
\ f, t =>
185 | MkRevealT (\ g => runRevealT t (g . f))
188 | promote : Functor x => SAlg f x -> Alg f (RevealT x)
190 | = inAlg f $
\ fo, sfo, rec, fr =>
191 | MkRevealT $
\ reveal =>
192 | let abstIn := \ fr => inMu (\ alg => reveal <$> outAlg f alg fo sfo (fo alg) fr) in
193 | outSAlg f salg reveal sfo abstIn (sfo salg) fr
196 | sfold : FoldT f (SAlg f) Dc
197 | sfold salg dc = runRevealT (fold (promote salg) dc) id
201 | inDc d = inMu (\ alg => outAlg f alg fold sfold (fold alg) d)
203 | out : Functor f => FoldT f (SAlg f) r -> r -> f r
204 | out sfo = sfo (inSAlg f (\ up, _, _, _ => map up))
206 | namespace Section5Sub1
209 | 0 list : Type -> Type
210 | list a = Dc (ListF a)
216 | Nil = inDc (ListF a) []
219 | (::) : a -> list a -> list a
220 | x :: xs = inDc (ListF a) (x :: xs)
223 | fromList : List a -> list a
224 | fromList = foldr (::) []
227 | 0 SpanF : Type -> Type -> Type
228 | SpanF a x = (List a, x)
230 | SpanSAlg : (a -> Bool) -> SAlg (ListF a) (SpanF a)
231 | SpanSAlg p = inSAlg (ListF a) $
\up, sfo, abstIn, span, xs =>
233 | [] => ([], abstIn xs)
236 | then let (r, s) = span xs' in (x :: r, up s)
237 | else ([], abstIn xs)
240 | spanr : FoldT (ListF a) (SAlg (ListF a)) r ->
241 | (a -> Bool) -> (xs : r) -> SpanF a r
242 | spanr sfo p xs = sfo (SpanSAlg p) @{MkFunctor mapSnd} xs
244 | breakr : FoldT (ListF a) (SAlg (ListF a)) r ->
245 | (a -> Bool) -> (xs : r) -> SpanF a r
246 | breakr sfo p = spanr sfo (not . p)
248 | WordsByAlg : (a -> Bool) -> Alg (ListF a) (const (List (List a)))
249 | WordsByAlg p = inAlg (ListF a) $
\ fo, sfo, wordsBy, xs =>
256 | let (w, rest) = breakr sfo p tl in
257 | (hd :: w) :: wordsBy rest
259 | wordsBy : (a -> Bool) -> (xs : List a) -> List (List a)
260 | wordsBy p = fold (ListF a) @{MkFunctor (const id)} (WordsByAlg p) . fromList
262 | namespace Section5Sub3
264 | data NatF x = Z | S x
269 | fromNat : Nat -> Section5Sub3.nat
270 | fromNat Z = inDc NatF Z
271 | fromNat (S n) = inDc NatF (S (fromNat n))
273 | toNat : Section5Sub3.nat -> Nat
274 | toNat = fold NatF @{MkFunctor (const id)} idAlg where
276 | idAlg : Alg NatF (const Nat)
277 | idAlg = inAlg NatF $
\ fo, sfo, toNat, n =>
280 | S n' => S (toNat n')
282 | zeroSAlg : SAlg NatF Prelude.id
283 | zeroSAlg = inSAlg NatF $
\ up, sfo, abstIn, zero, n =>
286 | S p => up (zero (zero p))
290 | zero = toNat . sfold NatF @{MkFunctor id} zeroSAlg . fromNat
292 | namespace Section5Sub3
294 | data TreeF a x = Node a (List x)
296 | 0 tree : Type -> Type
297 | tree a = Dc (TreeF a)
299 | node : a -> List (tree a) -> tree a
300 | node n ts = inDc (TreeF a) (Node n ts)
302 | mirrorAlg : SAlg (TreeF a) Prelude.id
303 | mirrorAlg = inSAlg (TreeF a) $
\ up, sfo, abstIn, mirror, t =>
304 | case t of Node a ts => abstIn (Node a $
map mirror (reverse ts))
306 | mirror : tree a -> tree a
307 | mirror = sfold (TreeF a) @{MkFunctor id} mirrorAlg
309 | namespace Section5Sub4
311 | 0 MappedT : (a, b : Type) -> Type
312 | MappedT a b = forall r. FoldT (ListF a) (SAlg (ListF a)) r -> a -> r -> (b, r)
314 | MapThroughAlg : MappedT a b -> Alg (ListF a) (const (List b))
315 | MapThroughAlg f = inAlg (ListF a) $
\fo, sfo, mapThrough, xs =>
319 | let (b, rest) = f sfo hd tl in
320 | b :: mapThrough rest
322 | mapThrough : MappedT a b -> list a -> List b
323 | mapThrough f = fold (ListF a) (MapThroughAlg f) @{MkFunctor (const id)}
325 | compressSpan : Eq a => MappedT a (Nat, a)
326 | compressSpan sfo hd tl
327 | = let (pref, rest) = spanr sfo (hd ==) tl in
328 | ((S (length pref), hd), rest)
330 | runLengthEncoding : Eq a => List a -> List (Nat, a)
331 | runLengthEncoding = mapThrough compressSpan . fromList
333 | namespace Section5Sub5
338 | MatchT : Type -> Type
339 | MatchT t = K t -> Bool
341 | data Regex = Zero | Exact Char | Sum Regex Regex | Cat Regex Regex | Plus Regex
343 | matchi : (t -> Regex -> MatchT t) -> Regex -> Char -> t -> MatchT t
344 | matchi matcher Zero c cs k = False
345 | matchi matcher (Exact c') c cs k = (c == c') && k cs
346 | matchi matcher (Sum r1 r2) c cs k = matchi matcher r1 c cs k || matchi matcher r2 c cs k
347 | matchi matcher (Cat r1 r2) c cs k = matchi matcher r1 c cs (\ cs => matcher cs r2 k)
348 | matchi matcher (Plus r) c cs k = matchi matcher r c cs (\ cs => k cs || matcher cs (Plus r) k)
350 | MatcherF : Type -> Type
351 | MatcherF t = Regex -> MatchT t
353 | functorMatcherF : Functor MatcherF
354 | functorMatcherF = MkFunctor (\ f, t, r, p => t r (p . f))
356 | MatcherAlg : Alg (ListF Char) MatcherF
357 | MatcherAlg = inAlg (ListF Char) $
\ fo, sfo, matcher, s =>
359 | [] => \ r, k => False
360 | (c :: cs) => \ r => matchi matcher r c cs
362 | match : Regex -> String -> Bool
363 | match r str = fold (ListF Char) MatcherAlg @{functorMatcherF} chars r isNil
366 | isNil : Mu (DcF (ListF Char)) -> Bool
367 | isNil = fold (ListF Char) {x = const Bool} @{MkFunctor (const id)}
368 | $
inAlg (ListF Char)
369 | $
\fo, sfo, rec, xs => case xs of
373 | chars : Mu (DcF (ListF Char))
374 | chars = fromList (unpack str)
377 | matchExample : Bool
378 | matchExample = match (Plus $
Cat (Sum (Exact 'a') (Exact 'b')) (Exact 'a')) "aabaaaba"
380 | namespace Section5Sub6
382 | parameters {0 a : Type} (ltA : a -> a -> Bool)
384 | 0 PartF : Type -> Type
385 | PartF x = a -> (x, x)
387 | PartSAlg : SAlg (ListF a) PartF
388 | PartSAlg = inSAlg (ListF a) $
\up, sfo, abstIn, partition, d, pivot => case d of
389 | [] => let xs = abstIn d in (xs, xs)
390 | x :: xs => let (l, r) = partition xs pivot in
391 | if ltA x pivot then (abstIn (x :: l), up r)
392 | else (up l, abstIn (x :: r))
394 | partr : (sfo : FoldT (ListF a) (SAlg (ListF a)) r) -> r -> a -> (r, r)
395 | partr sfo = sfo @{MkFunctor $
\ f, p, x => bimap f f (p x)} PartSAlg
397 | QuickSortAlg : Alg (ListF a) (const (List a))
398 | QuickSortAlg = inAlg (ListF a) $
\ fo, sfo, qsort, xs => case xs of
400 | p :: xs => let (l, r) = partr sfo xs p in
401 | qsort l ++ p :: qsort r
403 | quicksort : List a -> List a
404 | quicksort = fold (ListF a) QuickSortAlg @{MkFunctor (const id)} . fromList
407 | sortExample : String -> String
408 | sortExample = pack . quicksort (<=) . unpack