úÎ!À½j&      !"#$% Brent Yorgeybyorgey@gmail.comSafe4X_k¼n!simple-enumerationÿiAn enumeration of a finite or countably infinite set of values. An enumeration is represented as a function from the natural numbers (for infinite enumerations) or a finite prefix of the natural numbers (for finite ones) to values. Enumerations can thus easily be constructed for very large sets, and support efficient indexing and random sampling.. is an instance of the following type classes:&> (you can map a function over every element of an enumeration)'7 (representing Cartesian product of enumerations; see ())(4 (representing disjoint union of enumerations; see ()) is not a )(, since there is no way to implement P that works for any combination of finite and infinite enumerations (but see ).simple-enumeration&Get the cardinality of an enumeration.simple-enumerationÐSelect the value at a particular index of an enumeration. Precondition: the index must be strictly less than the cardinality. For infinite sets, every possible value must occur at some finite index.simple-enumerationAn index into an enumeration.simple-enumerationfThe cardinality of a countable set: either a specific finite natural number, or countably infinite.simple-enumeration&Test whether an enumeration is finite.isFinite (finiteList [1,2,3])True isFinite natFalsesimple-enumeration=List the elements of an enumeration in order. Inverse of  .*simple-enumeration=The empty enumeration, with cardinality zero and no elements. card voidFinite 0enumerate void[] simple-enumeration-The unit enumeration, with a single value of (). card unitFinite 1enumerate unit[()] simple-enumeration)An enumeration of a single given element.card (singleton 17)Finite 1enumerate (singleton 17)[17] simple-enumeration A constant infinite enumeration.card (always 17)Infinite enumerate . takeE 10 $ always 17[17,17,17,17,17,17,17,17,17,17] simple-enumeration'A finite prefix of the natural numbers.card (finite 5)Finite 5!card (finite 1234567890987654321)Finite 1234567890987654321enumerate (finite 5) [0,1,2,3,4]enumerate (finite 0)[] simple-enumeration0Construct an enumeration from the elements of a finite8 list. To turn an enumeration back into a list, use . enumerate (finiteList [2,3,8,1]) [2,3,8,1]select (finiteList [2,3,8,1]) 28 ÿ does not work on infinite lists: inspecting the cardinality of the resulting enumeration (something many of the enumeration combinators need to do) will hang trying to compute the length of the infinite list. To make an infinite enumeration, use something like f +  where f: is a function to compute the value at any given index.  uses (,ÿ%) internally, so you probably want to avoid using it on long lists. It would be possible to make a version with better indexing performance by allocating a vector internally, but I am too lazy to do it. If you have a good use case let me know (better yet, submit a pull request).simple-enumeration&Enumerate all the values of a bounded - instance.enumerate (boundedEnum @Bool) [False,True]select (boundedEnum @Char) 97'a'card (boundedEnum @Int)Finite 18446744073709551616select (boundedEnum @Int) 0-9223372036854775808simple-enumerationThe natural numbers,  0, 1, 2, ....enumerate . takeE 10 $ nat[0,1,2,3,4,5,6,7,8,9]simple-enumerationAll integers in the order 0, 1, -1, 2, -2, 3, -3, ....simple-enumeration>The positive rational numbers, enumerated according to the  Ahttp://www.cs.ox.ac.uk/publications/publication1664-abstract.htmlCalkin-Wilf sequence.enumerate . takeE 10 $ cw=[1 % 1,1 % 2,2 % 1,1 % 3,3 % 2,2 % 3,3 % 1,1 % 4,4 % 3,3 % 5]simple-enumeration|An enumeration of all rational numbers: 0 first, then each rational in the Calkin-Wilf sequence followed by its negative.enumerate . takeE 10 $ ratI[0 % 1,1 % 1,(-1) % 1,1 % 2,(-1) % 2,2 % 1,(-2) % 1,1 % 3,(-1) % 3,3 % 2]simple-enumeration<Take a finite prefix from the beginning of an enumeration.  takeE k e) always yields the empty enumeration for k \leq 0, and results in e whenever kO is greater than or equal to the cardinality of the enumeration. Otherwise  takeE k e has cardinality k and matches e from 0 to k-1.&enumerate $ takeE 3 (boundedEnum @Int)@[-9223372036854775808,-9223372036854775807,-9223372036854775806]'enumerate $ takeE 2 (finiteList [1..5])[1,2]'enumerate $ takeE 0 (finiteList [1..5])[]'enumerate $ takeE 7 (finiteList [1..5]) [1,2,3,4,5]simple-enumeration:Drop some elements from the beginning of an enumeration.  dropE k e yields e unchanged if k \leq 03, and results in the empty enumeration whenever k3 is greater than or equal to the cardinality of e.'enumerate $ dropE 2 (finiteList [1..5])[3,4,5]'enumerate $ dropE 0 (finiteList [1..5]) [1,2,3,4,5]'enumerate $ dropE 7 (finiteList [1..5])[]simple-enumerationÿ"Explicitly mark an enumeration as having an infinite cardinality, ignoring the previous cardinality. It is sometimes necessary to use this as a "hint" when constructing a recursive enumeration whose cardinality would otherwise consist of an infinite sum of finite cardinalities.0For example, consider the following definitions: _data Tree = L | B Tree Tree deriving Show treesBad :: Enumeration Tree treesBad = singleton L . B + treesBad /D treesBad trees :: Enumeration Tree trees = infinite $ singleton L . B + trees / trees Trying to use treeBada at all will simply hang, since trying to compute its cardinality leads to infinite recursion. %>>> select treesBad 5 ^CInterrupted. However, using , as in the definition of trees", provides the needed laziness: card treesInfiniteenumerate . takeE 3 $ trees[L,B L L,B L (B L L)]select trees 87239862967296ËB (B (B (B (B L L) (B (B (B L L) L) L)) (B L (B L (B L L)))) (B (B (B L (B L (B L L))) (B (B L L) (B L L))) (B (B L (B L (B L L))) L))) (B (B L (B (B (B L (B L L)) (B L L)) L)) (B (B (B L (B L L)) L) L))simple-enumerationFairly interleave a set of infinite enumerations.ÿuFor a finite set of infinite enumerations, a round-robin interleaving is used. That is, if we think of an enumeration of enumerations as a 2D matrix read off row-by-row, this corresponds to taking the transpose of a matrix with finitely many infinite rows, turning it into one with infinitely many finite rows. For an infinite set of infinite enumerations, i.e.P an infinite 2D matrix, the resulting enumeration reads off the matrix by s.Senumerate . takeE 15 $ interleave (finiteList [nat, negate <$> nat, (*10) <$> nat])'[0,0,0,1,-1,10,2,-2,20,3,-3,30,4,-4,40].enumerate . takeE 15 $ interleave (always nat)[0,0,1,0,1,2,0,1,2,3,0,1,2,3,4]This function is similar to  in a hypothetical ) instance for D, but it only works when the inner enumerations are all infinite.`To interleave a finite enumeration of enumerations, some of which may be finite, you can use  . f. If you want to interleave an infinite enumeration of finite enumerations, you are out of luck.simple-enumerationµZip two enumerations in parallel, producing the pair of elements at each index. The resulting enumeration is truncated to the cardinality of the smaller of the two arguments.(enumerate $ zipE nat (boundedEnum @Bool)[(0,False),(1,True)]simple-enumerationæZip two enumerations in parallel, applying the given function to the pair of elements at each index to produce a new element. The resulting enumeration is truncated to the cardinality of the smaller of the two arguments.Renumerate $ zipWithE replicate (finiteList [1..10]) (dropE 35 (boundedEnum @Char))V["#","$$","%%%","&&&&","'''''","((((((",")))))))","********","+++++++++",",,,,,,,,,,"]simple-enumerationSum, i.e.ÿm disjoint union, of two enumerations. If both are finite, all the values of the first will be enumerated before the values of the second. If only one is finite, the values from the finite enumeration will be listed first. If both are infinite, a fair (alternating) interleaving is used, so that every value ends up at a finite index in the result.Note that the () operator is a synonym for (.) from the ( instance for ,, which should be used in preference to (). (Q) is provided as a separate standalone operator to make it easier to document.+enumerate . takeE 10 $ singleton 17 <|> nat[17,0,1,2,3,4,5,6,7,8]+enumerate . takeE 10 $ nat <|> singleton 17[17,0,1,2,3,4,5,6,7,8]/enumerate . takeE 10 $ nat <|> (negate <$> nat)[0,0,1,-1,2,-2,3,-3,4,-4]–Note that this is not associative in a strict sense. In particular, it may fail to be associative when mixing finite and infinite enumerations:5enumerate . takeE 10 $ nat <|> (singleton 17 <|> nat)[0,17,1,0,2,1,3,2,4,3]5enumerate . takeE 10 $ (nat <|> singleton 17) <|> nat[17,0,0,1,1,2,2,3,3,4]4However, it is associative in several weaker senses:"If all the enumerations are finite$If all the enumerations are infinite”If enumerations are considered equivalent up to reordering (they are not, but considering them so may be acceptable in some applications).simple-enumeration$One half of the isomorphism between  \mathbb{N} and \mathbb{N} \times \mathbb{N}› which enumerates by diagonals: turn a particular natural number index into its position in the 2D grid. That is, given this numbering of a 2D grid: " 0 1 3 6 ... 2 4 7 5 8 9  maps 70 \mapsto (0,0), 1 \mapsto (0,1), 2 \mapsto (1,0) \dotssimple-enumerationÿ)Cartesian product of enumerations. If both are finite, uses a simple lexicographic ordering. If only one is finite, the resulting enumeration is still in lexicographic order, with the infinite enumeration as the most significant component. For two infinite enumerations, uses a fair  interleaving.2enumerate $ finiteList [1..3] >< finiteList "abcd"a[(1,'a'),(1,'b'),(1,'c'),(1,'d'),(2,'a'),(2,'b'),(2,'c'),(2,'d'),(3,'a'),(3,'b'),(3,'c'),(3,'d')].enumerate . takeE 10 $ finiteList "abc" >< natQ[('a',0),('b',0),('c',0),('a',1),('b',1),('c',1),('a',2),('b',2),('c',2),('a',3)].enumerate . takeE 10 $ nat >< finiteList "abc"Q[(0,'a'),(0,'b'),(0,'c'),(1,'a'),(1,'b'),(1,'c'),(2,'a'),(2,'b'),(2,'c'),(3,'a')]!enumerate . takeE 10 $ nat >< nat=[(0,0),(0,1),(1,0),(0,2),(1,1),(2,0),(0,3),(1,2),(2,1),(3,0)]Like (S), this operation is also not associative (not even up to reassociating tuples).simple-enumerationMEnumerate all possible values of type `Maybe a`, where the values of type a& are taken from the given enumeration.(enumerate $ maybeOf (finiteList [1,2,3])[Nothing,Just 1,Just 2,Just 3]simple-enumeration%Enumerae all possible values of type  Either a b8 with inner values taken from the given enumerations.&enumerate . takeE 6 $ eitherOf nat nat.[Left 0,Right 0,Left 1,Right 1,Left 2,Right 2]simple-enumerationJEnumerate all possible lists containing values from the given enumeration.!enumerate . takeE 15 $ listOf natZ[[],[0],[0,0],[1],[0,0,0],[1,0],[2],[0,1],[1,0,0],[2,0],[3],[0,0,0,0],[1,1],[2,0,0],[3,0]]simple-enumeration Cardinality has a Num“ instance for convenience, so we can use numeric literals as finite cardinalities, and add, subtract, and multiply cardinalities. Note that:subtraction is saturating (i.e. 3 - 5 = 0)&infinity - infinity is treated as zerodzero is treated as a "very strong" annihilator for multiplication: even infinity * zero = zero. simple-enumerationThe  Alternative instance for  Enumeration; represents the sum monoidal structure on enumerations: empty" is the empty enumeration, and (.) = () is disjoint union.!simple-enumerationThe  Applicative instance for  Enumeration/ works similarly to the instance for lists: pure = singleton, and f / x# takes the Cartesian product of f and x (see (4)) and applies each paired function and argument.  0      !"#$%&'()*+,-.,-/,-0,-12,34,56,78,-9,-:;-simple-enumeration-0.1-2M9vvkdlQNQ39MyMNnREziData.Enumeration Control.Monadjoin Data.Foldableasum EnumerationcardselectIndex CardinalityFiniteInfiniteisFinite enumerateunit singletonalwaysfinite finiteList boundedEnumnatintcwrattakeEdropEinfinite interleavezipEzipWithE<+>diagonal><maybeOfeitherOflistOf$fNumCardinality$fAlternativeEnumeration$fApplicativeEnumeration$fShowCardinality$fEqCardinality$fOrdCardinality$fFunctorEnumerationbaseGHC.BaseFunctor Applicative AlternativeMonadvoid Data.Functor<$>GHC.List!!GHC.EnumEnum<|><*>