0 | ||| This module provides interfaces similar to `Applicative`
1 | ||| and `Traversable` for heterogeneous container types.
2 | ||| We distinguish between two types of containers: Product
3 | ||| types hold all their values at once, while sum types
4 | ||| represent a choice: A generalization of `Either`.
5 | |||
6 | ||| The core data types in this library are indexed over a
7 | ||| container (typically a List or List of Lists) of values
8 | ||| of type `k` plus a type-level function `f` of type `k -> Type`.
9 | ||| The values of the container index together with `f` determine
10 | ||| the types of values at each position in the
11 | ||| heterogeneous product or sum, while the shape of container
12 | ||| indices mirror the shape of the corresponding product types.
13 | |||
14 | ||| The interfaces in this module allow us to create
15 | ||| hetereogeneous containers from sufficiently general functions
16 | ||| (`HPure`), use unary functions to change the context of
17 | ||| values in a heterogeneous container (`HFunctor`),
18 | ||| collapse heterogeneous containers into a single value (`HFoldable`)
19 | ||| and run an effectful computation over all values in
20 | ||| a heterogeneous container (`HSequence`).
21 | |||
22 | ||| In addition, `HFunctor` can be generalized to arbitrary
23 | ||| n-ary functions (`HAp`). However, this case is special in that only
24 | ||| the last argument of such a function can be a sum type
25 | ||| while all other arguments have to be product types.
26 | ||| This makes sense, since when combining values of two sum types,
27 | ||| we typically cannot guarantee that the values point at
28 | ||| same choice and are therefore compatible.
29 | |||
30 | ||| Implementation notes:
31 | |||
32 | ||| For many of the functions in this module, there is a constrained
33 | ||| version taking an implicit heterogeneous product holding
34 | ||| the desired implementations. Since Idris2 uses the same
35 | ||| mechanism for resolving interface constraints and auto implicits,
36 | ||| we do not need an additional structure or interface
37 | ||| for these constraints.
38 | ||| The disadvantage of this is, that we more often have to explicitly
39 | ||| pattern match on these constraint products in order for Idris2
40 | ||| to know where to look for implementations.
47 | ||| A heterogeneous container indexed over a container type `l`
48 | ||| holding values of type `k`.
49 | %inline
54 | --------------------------------------------------------------------------------
55 | -- HPure
56 | --------------------------------------------------------------------------------
58 | ||| This interface allows a heterogenous product to be filled
59 | ||| with values, given a function which produce values of
60 | ||| every possible type required.
61 | |||
62 | ||| @ k kind of Types in a heterogeneous container's type level code
63 | |||
64 | ||| @ l kind of container used to describe a heterogeneous containr's type
65 | ||| level code
66 | |||
67 | ||| @ p the heterogeneous sum or product
71 | ||| Creates a heterogeneous product by using the given functio
72 | ||| to produce values.
73 | |||
74 | ||| ```idris example
75 | ||| Person : (f : Type -> Type) -> Type
76 | ||| Person f = NP f [String,Int]
77 | |||
78 | ||| emptyPerson : Person Maybe
79 | ||| emptyPerson = hpure Nothing
80 | ||| ```
87 | ||| Alias for `hpure empty`.
88 | |||
89 | ||| ```idris example
90 | ||| Person : (f : Type -> Type) -> Type
91 | ||| Person f = NP f [String,Int]
92 | |||
93 | ||| emptyPerson : Person Maybe
94 | ||| emptyPerson = empty
95 | ||| ```
100 | ||| Fills a heterogeneous structure with a constant value
101 | ||| in the (K a) functor.
102 | |||
103 | ||| ```idris example
104 | ||| Person : (f : Type -> Type) -> Type
105 | ||| Person f = NP f [String,Int]
106 | |||
107 | ||| fooPerson : Person (K String)
108 | ||| fooPerson = hconst "foo"
109 | ||| ```
115 | --------------------------------------------------------------------------------
116 | -- HFunctor
117 | --------------------------------------------------------------------------------
119 | ||| A higher kinded functor allowing us to change the
120 | ||| wrapper type or context of an n-ary sum or product.
121 | |||
122 | ||| @ k kind of Types in a heterogeneous container's type level code
123 | |||
124 | ||| @ l kind of container used to describe a heterogeneous containr's type
125 | ||| level code
126 | |||
127 | ||| @ p the actual heterogeneous container
131 | ||| Maps the given function over all values in a
132 | ||| heterogeneous container, thus changing the context
133 | ||| of all of its values.
134 | |||
135 | ||| @ fun maps values in a heterogeneous container to a new context
136 | |||
137 | ||| @ p the heterogeneous container, over which `fun` is mapped.
138 | |||
139 | ||| ```idris example
140 | ||| Person : (f : Type -> Type) -> Type
141 | ||| Person f = NP f [String,Int]
142 | |||
143 | ||| toPersonMaybe : Person I -> Person Maybe
144 | ||| toPersonMaybe = hmap Just
145 | ||| ```
153 | ||| Alias for `hmap`
158 | ||| Like `hpure` but using a constrained function for
159 | ||| generating values. Since Idris is able to provide
160 | ||| the required constraints
161 | ||| already wrapped in a container of the correct
162 | ||| shape, this is actually a derivative of `HFunctor` and not
163 | ||| `HPure`. This has interesting consequences for sum
164 | ||| types, for which this function is available as well.
165 | ||| Since Idris has to choose a value of the sum
166 | ||| itself, it will use the first possibility it
167 | ||| can fill with the requested constraints.
168 | |||
169 | ||| In the first example below, Idris generates the value
170 | ||| `MkSOP (Z ["","",[]])`. However, if the first choice does
171 | ||| not have a Monoid instance, Idris faithfully chooses the
172 | ||| next working possibility. In the second example,
173 | ||| the result is `MkSOP (S (Z [[],[]]))`:
174 | |||
175 | ||| ```idris example
176 | ||| neutralFoo : SOP I [[String,String,List Int],[Int]]
177 | ||| neutralFoo = hcpure Monoid neutral
178 | |||
179 | ||| neutralBar : SOP I [[String,Int,List Int],[List String, List Int]]
180 | ||| neutralBar = hcpure Monoid neutral
181 | ||| ```
182 | |||
183 | ||| @ c erased function argument to specify the constraint
184 | ||| to use
185 | |||
186 | ||| @ fun generates values depending on the availability of
187 | ||| a constraint
197 | --------------------------------------------------------------------------------
198 | -- HAp
199 | --------------------------------------------------------------------------------
201 | ||| Like `Applicative`, this interface allows to
202 | ||| map arbitrary n-ary Rank-2 functions over
203 | ||| heterogeneous data structures of the same shape.
204 | ||| However, in order to support products as well as sum types
205 | ||| all arguments except the last one have to be products
206 | ||| indexed over the same container as the last argument.
207 | |||
208 | ||| @ k kind of Types in a heterogeneous container's type level code
209 | |||
210 | ||| @ l kind of container used to describe a heterogeneous containr's type
211 | ||| level code
212 | |||
213 | ||| @ q heterogeneous product related to `p`. For product types,
214 | ||| this is the same as `p`, for sum types it is the corresponding
215 | ||| product type.
216 | |||
217 | ||| @ p the actual heterogeneous container (sum or product)
221 | ||| Higher kinded equivalent to `(<*>)`.
222 | |||
223 | ||| Applies wrapped functions in the product
224 | ||| container to the corresponding values in the
225 | ||| second container.
226 | |||
227 | ||| @ q product holding unary Rank-2 functions.
228 | |||
229 | ||| @ p sum or product to whose values the functions in `q` should
230 | ||| be applied
231 | |||
232 | ||| ```idris example
233 | ||| hapTest : SOP Maybe [[String,Int]] -> SOP I [[String,Int]]
234 | ||| hapTest = hap (MkPOP $ [[fromMaybe "foo", const 12]])
235 | ||| ```
243 | ||| Higher kinded version of `liftA2`.
244 | ||| This is a generalization of `hliftA` to binary
245 | ||| functions.
255 | ||| Higher kinded version of `liftA3`.
256 | ||| This is a generalization of `hliftA` to ternary
257 | ||| functions.
269 | ||| Higher kinded version of `liftA4`.
270 | ||| This is a generalization of `hliftA` to quartenary
271 | ||| functions.
284 | ||| Like `hmap` but uses a constrained function.
285 | |||
286 | ||| @ c constraint used to convert values
287 | |||
288 | ||| @ fun constrained function for converting values to
289 | ||| a new context
290 | |||
291 | ||| ```idris example
292 | ||| showValues : NP I [String,Int] -> NP (K String) [String,Int]
293 | ||| showValues = hcmap Show show
294 | ||| ```
305 | ||| Alias for `hcmap`
316 | ||| Like `hliftA2` but with a constrained function.
329 | ||| Like `hliftA3` but with a constrained function.
343 | --------------------------------------------------------------------------------
344 | -- HFold
345 | --------------------------------------------------------------------------------
350 | ||| Strict fold over a heterogeneous sum or product
351 | ||| parameterized by the constant functor (and thus being actually
352 | ||| a homogeneous sum or product).
355 | ||| Lazy fold over a heterogeneous sum or product
356 | ||| parameterized by the constant functor (and thus being actually
357 | ||| a homogeneous sum or product).
366 | ||| Calculates the size of a heterogeneous container
371 | ||| Alias for `hfoldl (<+>) neutral`.
376 | ||| Alias for `hconcat . hmap fun`
387 | ||| Alias for `hconcat . hcmap c fun`
400 | ||| Generalization of `sequence_` to heterogeneous containers.
401 | |||
402 | ||| Alias for `hfoldl (*>) (pure ())`.
407 | ||| Generalization of `traverse_` to heterogeneous containers.
408 | |||
409 | ||| Alias for `hsequence_ . hmap fun`.
420 | ||| Generalization of `for_` to heterogeneous containers.
426 | ||| Generalization of `and` to heterogeneous containers.
431 | ||| Generalization of `toList` to heterogeneous containers.
432 | export
436 | ||| Generalization of `or` to heterogeneous containers.
437 | export
441 | ||| Generalization of `all` to heterogeneous containers.
442 | export
450 | ||| Generalization of `any` to heterogeneous containers.
451 | export
459 | ||| Generalization of `choice` to heterogeneous containers.
460 | export
464 | --------------------------------------------------------------------------------
465 | -- HSequence
466 | --------------------------------------------------------------------------------
468 | ||| Sequencing of applicative effects over a heterogeneous
469 | ||| container.
473 | ||| Given a heterogeneous containers holding values
474 | ||| wrapped in effect `g`, sequences applications of
475 | ||| `g` to the outside of the heterogeneous container.
476 | |||
477 | ||| ```idris example
478 | ||| seqMaybe : NP Maybe [Int,String] -> Maybe (NP I [Int,String])
479 | ||| seqMaybe = hsequence
480 | ||| ```
488 | ||| Traverses a heterogeneous container by applying effectful
489 | ||| function `fun`.
490 | |||
491 | ||| ```idris example
492 | ||| htraverseEx : NP (Either String) [Int,String] -> Maybe (NP I [Int,String])
493 | ||| htraverseEx = htraverse (either (const Nothing) Just)
494 | ||| ```
495 | export
506 | ||| Flipped version of `htraverse`.
507 | export
518 | ||| Constrained version of `htraverse`.
519 | |||
520 | ||| ```idris example
521 | ||| interface Read a where
522 | ||| read : String -> Maybe a
523 | |||
524 | ||| hctraverseEx : NP Read [Int,String] =>
525 | ||| NP (K String) [Int,String] -> Maybe (NP I [Int,String])
526 | ||| hctraverseEx = hctraverse Read read
527 | ||| ```
528 | export
541 | ||| Flipped version of `hctraverse`.
542 | export
555 | --------------------------------------------------------------------------------
556 | -- HCollapse
557 | --------------------------------------------------------------------------------
559 | ||| Collapsing a heterogeneous container to a homogeneous one
560 | ||| of the same shape.
564 | ||| A heterogeneous container over constant functor `K a` is
565 | ||| actually a homogeneous one holding only values of type `a`.
566 | ||| This function extracts the wrapped values into a homogeneous
567 | ||| one of the same size and shape.