| Copyright | Brent Yorgey Koji Miyazato |
|---|---|
| Maintainer | byorgey@gmail.com |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.ProEnumeration
Description
A proenumeration is a pair of a CoEnumeration and an Enumeration
sharing the same cardinality.
A proenumeration can be seen as a function with an explicitly enumerated range.
Through documentations of this module, these import aliases are used:
import qualified Data.Enumeration as E import qualified Data.CoEnumeration as C
Synopsis
- data ProEnumeration a b
- card :: ProEnumeration a b -> Cardinality
- select :: ProEnumeration a b -> Index -> b
- locate :: ProEnumeration a b -> a -> Index
- isFinite :: ProEnumeration a b -> Bool
- baseEnum :: ProEnumeration a b -> Enumeration b
- baseCoEnum :: ProEnumeration a b -> CoEnumeration a
- run :: ProEnumeration a b -> a -> b
- enumerateRange :: ProEnumeration a b -> [b]
- unsafeMkProEnumeration :: Cardinality -> (Index -> b) -> (a -> Index) -> ProEnumeration a b
- mkProEnumeration :: CoEnumeration a -> Enumeration b -> ProEnumeration a b
- dimap :: (a' -> a) -> (b -> b') -> ProEnumeration a b -> ProEnumeration a' b'
- (.@) :: (a' -> a) -> ProEnumeration a b -> ProEnumeration a' b
- (@.) :: ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
- data Cardinality
- type Index = Integer
- unit :: ProEnumeration a ()
- empty :: ProEnumeration Void b
- singleton :: b -> ProEnumeration a b
- modulo :: Integer -> ProEnumeration Integer Integer
- clamped :: Integer -> Integer -> ProEnumeration Integer Integer
- boundsChecked :: Integer -> Integer -> ProEnumeration Integer (Maybe Integer)
- finiteList :: [a] -> ProEnumeration Integer (Maybe a)
- finiteCycle :: [a] -> ProEnumeration Integer a
- boundedEnum :: (Enum a, Bounded a) => ProEnumeration a a
- nat :: ProEnumeration Integer Integer
- int :: ProEnumeration Integer Integer
- cw :: ProEnumeration Rational Rational
- rat :: ProEnumeration Rational Rational
- infinite :: ProEnumeration a b -> ProEnumeration a b
- compose :: ProEnumeration a b -> ProEnumeration b c -> ProEnumeration a c
- (><) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (a1, a2) (b1, b2)
- (<+>) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (Either a1 a2) (Either b1 b2)
- maybeOf :: ProEnumeration a b -> ProEnumeration (Maybe a) (Maybe b)
- eitherOf :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (Either a1 a2) (Either b1 b2)
- listOf :: ProEnumeration a b -> ProEnumeration [a] [b]
- finiteSubsetOf :: ProEnumeration a b -> ProEnumeration [a] [b]
- enumerateP :: CoEnumeration a -> Enumeration b -> Enumeration (ProEnumeration a b)
- coenumerateP :: Enumeration a -> CoEnumeration b -> CoEnumeration (a -> b)
- proenumerationOf :: ProEnumeration a a' -> ProEnumeration b b' -> ProEnumeration (a' -> b) (ProEnumeration a b')
- finiteFunctionOf :: Integer -> ProEnumeration a b -> ProEnumeration (Integer -> a) (Integer -> b)
Proenumeration type
data ProEnumeration a b Source #
A proenumeration is a pair of a CoEnumeration and an Enumeration
sharing the same cardinality.
Alternatively, a proenumeration can be seen as a function with an
explicitly enumerated range.
Through this documentation, proenumerations are shown in diagrams of the following shape:
f g a ---> N ---> b :: ProEnumeration a b
Which means it is a value p :: ProEnumeration a b with
cardinality N, locate p = f, and select p = g.
We can see N in the diagram as a subset of integers:
N = {i :: Integer | i < N}Then it is actually a (category-theoretic)
diagram showing values of ProEnumeration a b.
Instances
| Functor (ProEnumeration a) Source # | |
Defined in Data.ProEnumeration Methods fmap :: (a0 -> b) -> ProEnumeration a a0 -> ProEnumeration a b # (<$) :: a0 -> ProEnumeration a b -> ProEnumeration a a0 # | |
card :: ProEnumeration a b -> Cardinality Source #
Get the cardinality of a proenumeration
isFinite :: ProEnumeration a b -> Bool Source #
Returns if the the cardinality of a proenumeration is finite.
baseEnum :: ProEnumeration a b -> Enumeration b Source #
Take an Enumeration from a proenumeration,
discarding the CoEnumeration part
baseCoEnum :: ProEnumeration a b -> CoEnumeration a Source #
Take an CoEnumeration from a proenumeration,
discarding Enumeration part
run :: ProEnumeration a b -> a -> b Source #
Turn a proenumeration into a normal function.
run p = (select p :: Index -> b) . (locate p :: a -> Index)
enumerateRange :: ProEnumeration a b -> [b] Source #
enumerateRange = E.enumerate . baseEnumunsafeMkProEnumeration :: Cardinality -> (Index -> b) -> (a -> Index) -> ProEnumeration a b Source #
Constructs a proenumeration.
To construct a valid proenumeration by unsafeMkProEnumeration n f g,
it must satisfy the following conditions:
- For all
i :: Integer, if0 <= i && i < n, thenf ishould be "valid" (usually, it meansf ishould evaluate without exception). - For all
x :: a,(Finite (g x) < n).
This functions does not (and never could) check the validity of its arguments.
mkProEnumeration :: CoEnumeration a -> Enumeration b -> ProEnumeration a b Source #
Constructs a proenumeration from a CoEnumeration and an Enumeration.
The cardinalities of the two arguments must be equal.
Otherwise, mkProEnumeration returns an error.
baseEnum (mkProEnumeration a b) = b baseCoEnum (mkProEnumeration a b) = a
>>>p = mkProEnumeration (C.modulo 3) (E.finiteList "abc")>>>(card p, locate p 4, select p 1)(Finite 3,1,'b')
ProEnumeration is a Profunctor
dimap :: (a' -> a) -> (b -> b') -> ProEnumeration a b -> ProEnumeration a' b' Source #
ProEnumeration is a Profunctor
dimap l r p = l .@ p @. r
(.@) :: (a' -> a) -> ProEnumeration a b -> ProEnumeration a' b infixr 8 Source #
l .@ p = dimap l id p
(@.) :: ProEnumeration a b -> (b -> b') -> ProEnumeration a b' infixl 7 Source #
p @. r = dimap id r p
Using Cardinality
data Cardinality Source #
The cardinality of a countable set: either a specific finite natural number, or countably infinite.
Instances
Primitive proenumerations
unit :: ProEnumeration a () Source #
unit =mkProEnumerationC.unitE.unit
empty :: ProEnumeration Void b Source #
empty =mkProEnumerationlostempty
singleton :: b -> ProEnumeration a b Source #
singleton b = b <$unit=mkProEnumerationC.unit(E.singletonb)
modulo :: Integer -> ProEnumeration Integer Integer Source #
modulo k =mkProEnumeration(C.modulok) (E.finitek)
>>>card (modulo 13) == Finite 13True>>>run (modulo 13) 1462325 == 1462325 `mod` 13True
clamped :: Integer -> Integer -> ProEnumeration Integer Integer Source #
clamped lo hi is a proenumeration of integers,
which does not modify integers between lo and hi, inclusive,
and limits smaller (larger) integer to lo (hi).
It is an error to call this function if lo > hi.
run (clamped lo hi) = min hi . max lo
>>>card (clamped (-2) 2)Finite 5>>>enumerateRange (clamped (-2) 2)[-2,-1,0,1,2]>>>run (clamped (-2) 2) <$> [-4 .. 4][-2,-2,-2,-1,0,1,2,2,2]
boundsChecked :: Integer -> Integer -> ProEnumeration Integer (Maybe Integer) Source #
boundsChecked lo hi is a proenumeration of a "bounds check" function,
which validates that an input is between lo and hi, inclusive,
and returns Nothing if it is outside those bounds.
run (boundsChecked lo hi) i
| lo <= i && i <= hi = Just i | otherwise = Nothing
>>>card (boundsChecked (-2) 2)Finite 6>>>-- Justs of [-2 .. 2] and Nothing>>>enumerateRange (boundsChecked (-2) 2)[Just (-2),Just (-1),Just 0,Just 1,Just 2,Nothing]>>>run (boundsChecked (-2) 2) <$> [-4 .. 4][Nothing,Nothing,Just (-2),Just (-1),Just 0,Just 1,Just 2,Nothing,Nothing]
finiteList :: [a] -> ProEnumeration Integer (Maybe a) Source #
finiteList as is a proenumeration of a "bounds checked"
indexing of as.
run (finiteList as) i
| 0 <= i && i < length as = Just (as !! i) | otherwise = Nothing
Note that finiteList uses !! on the input list
under the hood, which has bad performance for long lists.
See also the documentation of Data.Enumeration.finiteList.
>>> card (finiteList HELLO)
Finite 6
>>> -- Justs and Nothing
>>> enumerateRange (finiteList HELLO)
[Just H,Just E,Just L,Just L,Just O,Nothing]
>>> run (finiteList HELLO) $ [0 .. 6]
[Just H,Just E,Just L,Just L,Just O,Nothing,Nothing]
finiteCycle :: [a] -> ProEnumeration Integer a Source #
finiteCycle as is a proenumeration of an indexing of as,
where every integer is a valid index by taking it modulo length as.
run (finiteCycle as) i = as !! (i `mod` length as)
If as is an empty list, it is an error.
>>>card (finiteCycle "HELLO")Finite 5>>>enumerateRange (finiteCycle "HELLO")"HELLO">>>run (finiteCycle "HELLO") <$> [0 .. 10]"HELLOHELLOH"
boundedEnum :: (Enum a, Bounded a) => ProEnumeration a a Source #
boundedEnum =mkProEnumerationC.boundedEnumE.boundedEnum
nat :: ProEnumeration Integer Integer Source #
nat =mkProEnumerationC.natE.nat
int :: ProEnumeration Integer Integer Source #
int =mkProEnumerationC.intE.int
cw :: ProEnumeration Rational Rational Source #
cw =mkProEnumerationC.cwE.cw
rat :: ProEnumeration Rational Rational Source #
rat =mkProEnumerationC.ratE.rat
Combinators
infinite :: ProEnumeration a b -> ProEnumeration a b Source #
Sets the cardinality of given proenumeration to Infinite
compose :: ProEnumeration a b -> ProEnumeration b c -> ProEnumeration a c Source #
From two proenumerations p, q, we can make a proenumeration
compose p q which behaves as a composed function
(in diagrammatic order like >>>.)
run (compose p q) = run q . run p
p and q can be drawn in a diagram as follows:
[_______p______] [______q______] lp sp lq sq a ----> N ----> b ----> M ----> c
To get a proenumeration a -> ?? -> c, there are two obvious choices:
run p >>> lq sq a --------------------> M ----> c lp sp >>> run q a ----> N --------------------> c
This function chooses the option with the smaller cardinality.
(><) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (a1, a2) (b1, b2) Source #
Cartesian product of proenumerations.
p >= 'mkProEnumeration' (baseCoEnum p C.'C.<' baseCoEnum q)
(baseEnum p E.>< baseEnum q)
This operation is not associative if and only if one of the arguments is not finite.
(<+>) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (Either a1 a2) (Either b1 b2) Source #
Disjoint sum of proenumerations.
p + q =mkProEnumeration(baseCoEnum p C.<+>baseCoEnum q) (baseEnum p `E.eitherOf'baseEnum q)
This operation is not associative if and only if one of the arguments is not finite.
maybeOf :: ProEnumeration a b -> ProEnumeration (Maybe a) (Maybe b) Source #
maybeOf p =mkProEnumeration(C.maybeOf(baseCoEnum p)) (E.maybeOf(baseEnum p))
eitherOf :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (Either a1 a2) (Either b1 b2) Source #
Synonym of (<+>)
listOf :: ProEnumeration a b -> ProEnumeration [a] [b] Source #
listOf p =mkProEnumeration(C.listOf(baseCoEnum p)) (E.listOf(baseEnum p))
finiteSubsetOf :: ProEnumeration a b -> ProEnumeration [a] [b] Source #
finiteSubsetOf p =mkProEnumeration(C.finiteSubsetOf(baseCoEnum p)) (E.finiteSubsetOf(baseEnum p))
enumerateP :: CoEnumeration a -> Enumeration b -> Enumeration (ProEnumeration a b) Source #
Enumerate every possible proenumeration.
enumerateP a b generates proenumerations p
such that the function run p has the following properties:
- The range of
run pis a subset ofb :: Enumeration b. - If
locate a x = locate a y, thenrun p x = run p y. In other words,run pfactors throughlocate a.
This function generates proenumerations p in such a way that
every function of type a -> b with the above properties uniquely
appears as run p for some enumerated p.
coenumerateP :: Enumeration a -> CoEnumeration b -> CoEnumeration (a -> b) Source #
Coenumerate every possible function.
coenumerateP as bs classifies functions of type a -> b
by the following criterion:
f and g have the same index
if and only if
For all elements a of as :: Enumeration a,
locate bs (f a) = locate bs (g a).
Note: The suffix P suggests it coenumerates ProEnumeration a b,
but it actually coenumerates a -> b. The reason is that
ProEnumeration a b carries extra data and constraints like its cardinality,
but the classification does not care about those. Thus, it is more permissive to
accept any function of type a -> b.
To force it to coenumerate proenumerations,
can be applied.contramap run
proenumerationOf :: ProEnumeration a a' -> ProEnumeration b b' -> ProEnumeration (a' -> b) (ProEnumeration a b') Source #
enumerateP and coenumerateP combined.
l_a s_a a -----> N -----> a' :: ProEnumeration a a' l_b s_b b -----> M -----> b' :: ProEnumeration b b' (N -> b) ---> (N -> M) ---> (N -> b') ^ || | | (. s_a) || | (. l_a) | || v (a' -> b) (M ^ N) (a -> b')
- When
Nis finite,(M ^ N)is at most countable, sinceMis at most countable. - The enumerated functions (of type
a -> b') are compositions ofl_a :: a -> Nand functions of typeN -> b. It is beneficial to tell this fact by the type, which happens to beProEnumeration a b'.
finiteFunctionOf :: Integer -> ProEnumeration a b -> ProEnumeration (Integer -> a) (Integer -> b) Source #
finiteFunctionOf k p is a proenumeration of products of k copies of
a and b respectively.
If p is a invertible enumeration, finiteFunctionOf k p is too.
It is implemented using proenumerationOf.