{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Data.ProEnumeration(
ProEnumeration()
, card, select, locate
, isFinite
, baseEnum, baseCoEnum, run
, enumerateRange
, unsafeMkProEnumeration
, mkProEnumeration
, dimap, (.@), (@.)
, Cardinality(..), Index
, unit, empty
, singleton
, modulo, clamped, boundsChecked
, finiteList, finiteCycle
, boundedEnum
, nat, int, cw, rat
, infinite
, compose
, (><), (<+>)
, maybeOf, eitherOf
, listOf, finiteSubsetOf
, enumerateP, coenumerateP
, proenumerationOf
, finiteFunctionOf
) where
import qualified Control.Applicative as Ap (Alternative (empty))
import Data.Void
import Data.Functor.Contravariant
import Data.CoEnumeration (CoEnumeration)
import qualified Data.CoEnumeration as C
import Data.Enumeration (Cardinality (..), Enumeration,
Index)
import qualified Data.Enumeration as E
data ProEnumeration a b =
ProEnumeration {
forall a b. ProEnumeration a b -> Cardinality
card :: Cardinality
, forall a b. ProEnumeration a b -> Integer -> b
select :: Index -> b
, forall a b. ProEnumeration a b -> a -> Integer
locate :: a -> Index
}
deriving ((forall a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b)
-> (forall a b. a -> ProEnumeration a b -> ProEnumeration a a)
-> Functor (ProEnumeration a)
forall a b. a -> ProEnumeration a b -> ProEnumeration a a
forall a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b
forall a a b. a -> ProEnumeration a b -> ProEnumeration a a
forall a a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b
fmap :: forall a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b
$c<$ :: forall a a b. a -> ProEnumeration a b -> ProEnumeration a a
<$ :: forall a b. a -> ProEnumeration a b -> ProEnumeration a a
Functor)
isFinite :: ProEnumeration a b -> Bool
isFinite :: forall a b. ProEnumeration a b -> Bool
isFinite = (Cardinality -> Cardinality -> Bool
forall a. Eq a => a -> a -> Bool
/= Cardinality
Infinite) (Cardinality -> Bool)
-> (ProEnumeration a b -> Cardinality)
-> ProEnumeration a b
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProEnumeration a b -> Cardinality
forall a b. ProEnumeration a b -> Cardinality
card
dimap :: (a' -> a) -> (b -> b') -> ProEnumeration a b -> ProEnumeration a' b'
dimap :: forall a' a b b'.
(a' -> a)
-> (b -> b') -> ProEnumeration a b -> ProEnumeration a' b'
dimap a' -> a
l b -> b'
r ProEnumeration a b
p = ProEnumeration a b
p{ select = r . select p, locate = locate p . l }
(@.) :: ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
@. :: forall a b b'.
ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
(@.) = ((b -> b') -> ProEnumeration a b -> ProEnumeration a b')
-> ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
forall a b c. (a -> b -> c) -> b -> a -> c
flip (b -> b') -> ProEnumeration a b -> ProEnumeration a b'
forall a b. (a -> b) -> ProEnumeration a a -> ProEnumeration a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
infixl 7 @.
(.@) :: (a' -> a) -> ProEnumeration a b -> ProEnumeration a' b
a' -> a
l .@ :: forall a' a b.
(a' -> a) -> ProEnumeration a b -> ProEnumeration a' b
.@ ProEnumeration a b
p = ProEnumeration a b
p{ locate = locate p . l }
infixr 8 .@
baseEnum :: ProEnumeration a b -> Enumeration b
baseEnum :: forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a b
p = Cardinality -> (Integer -> b) -> Enumeration b
forall a. Cardinality -> (Integer -> a) -> Enumeration a
E.mkEnumeration (ProEnumeration a b -> Cardinality
forall a b. ProEnumeration a b -> Cardinality
card ProEnumeration a b
p) (ProEnumeration a b -> Integer -> b
forall a b. ProEnumeration a b -> Integer -> b
select ProEnumeration a b
p)
baseCoEnum :: ProEnumeration a b -> CoEnumeration a
baseCoEnum :: forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a b
p = Cardinality -> (a -> Integer) -> CoEnumeration a
forall a. Cardinality -> (a -> Integer) -> CoEnumeration a
C.unsafeMkCoEnumeration (ProEnumeration a b -> Cardinality
forall a b. ProEnumeration a b -> Cardinality
card ProEnumeration a b
p) (ProEnumeration a b -> a -> Integer
forall a b. ProEnumeration a b -> a -> Integer
locate ProEnumeration a b
p)
run :: ProEnumeration a b -> a -> b
run :: forall a b. ProEnumeration a b -> a -> b
run ProEnumeration a b
p = ProEnumeration a b -> Integer -> b
forall a b. ProEnumeration a b -> Integer -> b
select ProEnumeration a b
p (Integer -> b) -> (a -> Integer) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProEnumeration a b -> a -> Integer
forall a b. ProEnumeration a b -> a -> Integer
locate ProEnumeration a b
p
enumerateRange :: ProEnumeration a b -> [b]
enumerateRange :: forall a b. ProEnumeration a b -> [b]
enumerateRange = Enumeration b -> [b]
forall a. Enumeration a -> [a]
E.enumerate (Enumeration b -> [b])
-> (ProEnumeration a b -> Enumeration b)
-> ProEnumeration a b
-> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProEnumeration a b -> Enumeration b
forall a b. ProEnumeration a b -> Enumeration b
baseEnum
mkProEnumeration :: CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration :: forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
a Enumeration b
b
| Cardinality
na Cardinality -> Cardinality -> Bool
forall a. Eq a => a -> a -> Bool
== Cardinality
nb = ProEnumeration a b
p
| Bool
otherwise = [Char] -> ProEnumeration a b
forall a. HasCallStack => [Char] -> a
error ([Char] -> ProEnumeration a b) -> [Char] -> ProEnumeration a b
forall a b. (a -> b) -> a -> b
$ [Char]
"mkProEnumeration cardinality mismatch:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Cardinality, Cardinality) -> [Char]
forall a. Show a => a -> [Char]
show (Cardinality
na, Cardinality
nb)
where
na :: Cardinality
na = CoEnumeration a -> Cardinality
forall a. CoEnumeration a -> Cardinality
C.card CoEnumeration a
a
nb :: Cardinality
nb = Enumeration b -> Cardinality
forall a. Enumeration a -> Cardinality
E.card Enumeration b
b
p :: ProEnumeration a b
p = ProEnumeration{ card :: Cardinality
card = Cardinality
na, select :: Integer -> b
select = Enumeration b -> Integer -> b
forall a. Enumeration a -> Integer -> a
E.select Enumeration b
b, locate :: a -> Integer
locate = CoEnumeration a -> a -> Integer
forall a. CoEnumeration a -> a -> Integer
C.locate CoEnumeration a
a }
unsafeMkProEnumeration
:: Cardinality-> (Index -> b) -> (a -> Index) -> ProEnumeration a b
unsafeMkProEnumeration :: forall b a.
Cardinality
-> (Integer -> b) -> (a -> Integer) -> ProEnumeration a b
unsafeMkProEnumeration = Cardinality
-> (Integer -> b) -> (a -> Integer) -> ProEnumeration a b
forall a b.
Cardinality
-> (Integer -> b) -> (a -> Integer) -> ProEnumeration a b
ProEnumeration
unit :: ProEnumeration a ()
unit :: forall a. ProEnumeration a ()
unit = CoEnumeration a -> Enumeration () -> ProEnumeration a ()
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
forall a. CoEnumeration a
C.unit Enumeration ()
E.unit
singleton :: b -> ProEnumeration a b
singleton :: forall b a. b -> ProEnumeration a b
singleton b
b = CoEnumeration a -> Enumeration b -> ProEnumeration a b
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
forall a. CoEnumeration a
C.unit (b -> Enumeration b
forall a. a -> Enumeration a
E.singleton b
b)
empty :: ProEnumeration Void b
empty :: forall b. ProEnumeration Void b
empty = CoEnumeration Void -> Enumeration b -> ProEnumeration Void b
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration Void
forall (f :: * -> *). Decidable f => f Void
C.lost Enumeration b
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
Ap.empty
boundedEnum :: (Enum a, Bounded a) => ProEnumeration a a
boundedEnum :: forall a. (Enum a, Bounded a) => ProEnumeration a a
boundedEnum = CoEnumeration a -> Enumeration a -> ProEnumeration a a
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
forall a. (Enum a, Bounded a) => CoEnumeration a
C.boundedEnum Enumeration a
forall a. (Enum a, Bounded a) => Enumeration a
E.boundedEnum
modulo :: Integer -> ProEnumeration Integer Integer
modulo :: Integer -> ProEnumeration Integer Integer
modulo Integer
k = CoEnumeration Integer
-> Enumeration Integer -> ProEnumeration Integer Integer
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration (Integer -> CoEnumeration Integer
C.modulo Integer
k) (Integer -> Enumeration Integer
E.finite Integer
k)
clamped :: Integer -> Integer -> ProEnumeration Integer Integer
clamped :: Integer -> Integer -> ProEnumeration Integer Integer
clamped Integer
lo Integer
hi
| Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
hi = ProEnumeration
{ card :: Cardinality
card = Integer -> Cardinality
Finite (Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
hi Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo)
, select :: Integer -> Integer
select = (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
lo)
, locate :: Integer -> Integer
locate = \Integer
i -> Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
min (Integer
hi Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo) (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
0 (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo))
}
| Bool
otherwise = [Char] -> ProEnumeration Integer Integer
forall a. HasCallStack => [Char] -> a
error [Char]
"Empty range"
boundsChecked :: Integer -> Integer -> ProEnumeration Integer (Maybe Integer)
boundsChecked :: Integer -> Integer -> ProEnumeration Integer (Maybe Integer)
boundsChecked Integer
lo Integer
hi = ProEnumeration
{ card :: Cardinality
card = Integer -> Cardinality
Finite Integer
size
, select :: Integer -> Maybe Integer
select = Integer -> Maybe Integer
sel
, locate :: Integer -> Integer
locate = Integer -> Integer
loc
}
where
n :: Integer
n = Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
hi Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo
size :: Integer
size = Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
0 Integer
n
sel :: Integer -> Maybe Integer
sel Integer
i
| Integer
0 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
i Bool -> Bool -> Bool
&& Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
n = Integer -> Maybe Integer
forall a. a -> Maybe a
Just (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
lo)
| Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
n = Maybe Integer
forall a. Maybe a
Nothing
| Bool
otherwise = [Char] -> Maybe Integer
forall a. HasCallStack => [Char] -> a
error [Char]
"out of bounds"
loc :: Integer -> Integer
loc Integer
k | Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
k Bool -> Bool -> Bool
&& Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
hi = Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo
| Bool
otherwise = Integer
n
finiteList :: [a] -> ProEnumeration Integer (Maybe a)
finiteList :: forall a. [a] -> ProEnumeration Integer (Maybe a)
finiteList [a]
as = Integer -> Integer -> ProEnumeration Integer (Maybe Integer)
boundsChecked Integer
0 (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1) ProEnumeration Integer (Maybe Integer)
-> (Maybe Integer -> Maybe a) -> ProEnumeration Integer (Maybe a)
forall a b b'.
ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
@. ((Integer -> a) -> Maybe Integer -> Maybe a
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> a
sel)
where
as' :: Enumeration a
as' = [a] -> Enumeration a
forall a. [a] -> Enumeration a
E.finiteList [a]
as
Finite Integer
n = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
E.card Enumeration a
as'
sel :: Integer -> a
sel = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select Enumeration a
as'
finiteCycle :: [a] -> ProEnumeration Integer a
finiteCycle :: forall a. [a] -> ProEnumeration Integer a
finiteCycle [a]
as = Integer -> ProEnumeration Integer Integer
modulo Integer
n ProEnumeration Integer Integer
-> (Integer -> a) -> ProEnumeration Integer a
forall a b b'.
ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
@. Integer -> a
sel
where
as' :: Enumeration a
as' = [a] -> Enumeration a
forall a. [a] -> Enumeration a
E.finiteList [a]
as
Finite Integer
n = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
E.card Enumeration a
as'
sel :: Integer -> a
sel = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select Enumeration a
as'
nat :: ProEnumeration Integer Integer
nat :: ProEnumeration Integer Integer
nat = CoEnumeration Integer
-> Enumeration Integer -> ProEnumeration Integer Integer
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration Integer
C.nat Enumeration Integer
E.nat
int :: ProEnumeration Integer Integer
int :: ProEnumeration Integer Integer
int = CoEnumeration Integer
-> Enumeration Integer -> ProEnumeration Integer Integer
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration Integer
C.int Enumeration Integer
E.int
cw :: ProEnumeration Rational Rational
cw :: ProEnumeration Rational Rational
cw = CoEnumeration Rational
-> Enumeration Rational -> ProEnumeration Rational Rational
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration Rational
C.cw Enumeration Rational
E.cw
rat :: ProEnumeration Rational Rational
rat :: ProEnumeration Rational Rational
rat = CoEnumeration Rational
-> Enumeration Rational -> ProEnumeration Rational Rational
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration Rational
C.rat Enumeration Rational
E.rat
infinite :: ProEnumeration a b -> ProEnumeration a b
infinite :: forall a b. ProEnumeration a b -> ProEnumeration a b
infinite ProEnumeration a b
p = ProEnumeration a b
p{ card = Infinite }
compose :: ProEnumeration a b -> ProEnumeration b c -> ProEnumeration a c
compose :: forall a b c.
ProEnumeration a b -> ProEnumeration b c -> ProEnumeration a c
compose ProEnumeration a b
p ProEnumeration b c
q
| ProEnumeration a b -> Cardinality
forall a b. ProEnumeration a b -> Cardinality
card ProEnumeration a b
p Cardinality -> Cardinality -> Bool
forall a. Ord a => a -> a -> Bool
<= ProEnumeration b c -> Cardinality
forall a b. ProEnumeration a b -> Cardinality
card ProEnumeration b c
q = ProEnumeration a b
p ProEnumeration a b -> (b -> c) -> ProEnumeration a c
forall a b b'.
ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
@. ProEnumeration b c -> b -> c
forall a b. ProEnumeration a b -> a -> b
run ProEnumeration b c
q
| Bool
otherwise = ProEnumeration a b -> a -> b
forall a b. ProEnumeration a b -> a -> b
run ProEnumeration a b
p (a -> b) -> ProEnumeration b c -> ProEnumeration a c
forall a' a b.
(a' -> a) -> ProEnumeration a b -> ProEnumeration a' b
.@ ProEnumeration b c
q
(><) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2 -> ProEnumeration (a1,a2) (b1,b2)
ProEnumeration a1 b1
p >< :: forall a1 b1 a2 b2.
ProEnumeration a1 b1
-> ProEnumeration a2 b2 -> ProEnumeration (a1, a2) (b1, b2)
>< ProEnumeration a2 b2
q = CoEnumeration (a1, a2)
-> Enumeration (b1, b2) -> ProEnumeration (a1, a2) (b1, b2)
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration (ProEnumeration a1 b1 -> CoEnumeration a1
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a1 b1
p CoEnumeration a1 -> CoEnumeration a2 -> CoEnumeration (a1, a2)
forall a b.
CoEnumeration a -> CoEnumeration b -> CoEnumeration (a, b)
C.>< ProEnumeration a2 b2 -> CoEnumeration a2
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a2 b2
q) (ProEnumeration a1 b1 -> Enumeration b1
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a1 b1
p Enumeration b1 -> Enumeration b2 -> Enumeration (b1, b2)
forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
E.>< ProEnumeration a2 b2 -> Enumeration b2
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a2 b2
q)
(<+>) :: ProEnumeration a1 b1 -> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
ProEnumeration a1 b1
p <+> :: forall a1 b1 a2 b2.
ProEnumeration a1 b1
-> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
<+> ProEnumeration a2 b2
q = CoEnumeration (Either a1 a2)
-> Enumeration (Either b1 b2)
-> ProEnumeration (Either a1 a2) (Either b1 b2)
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration (ProEnumeration a1 b1 -> CoEnumeration a1
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a1 b1
p CoEnumeration a1
-> CoEnumeration a2 -> CoEnumeration (Either a1 a2)
forall a b.
CoEnumeration a -> CoEnumeration b -> CoEnumeration (Either a b)
C.<+> ProEnumeration a2 b2 -> CoEnumeration a2
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a2 b2
q) (Enumeration b1 -> Enumeration b2 -> Enumeration (Either b1 b2)
forall a b.
Enumeration a -> Enumeration b -> Enumeration (Either a b)
E.eitherOf (ProEnumeration a1 b1 -> Enumeration b1
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a1 b1
p) (ProEnumeration a2 b2 -> Enumeration b2
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a2 b2
q))
maybeOf :: ProEnumeration a b -> ProEnumeration (Maybe a) (Maybe b)
maybeOf :: forall a b.
ProEnumeration a b -> ProEnumeration (Maybe a) (Maybe b)
maybeOf ProEnumeration a b
p = (Maybe a -> Either () a)
-> (Either () b -> Maybe b)
-> ProEnumeration (Either () a) (Either () b)
-> ProEnumeration (Maybe a) (Maybe b)
forall a' a b b'.
(a' -> a)
-> (b -> b') -> ProEnumeration a b -> ProEnumeration a' b'
dimap (Either () a -> (a -> Either () a) -> Maybe a -> Either () a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Either () a
forall a b. a -> Either a b
Left ()) a -> Either () a
forall a b. b -> Either a b
Right) ((() -> Maybe b) -> (b -> Maybe b) -> Either () b -> Maybe b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe b -> () -> Maybe b
forall a b. a -> b -> a
const Maybe b
forall a. Maybe a
Nothing) b -> Maybe b
forall a. a -> Maybe a
Just) (ProEnumeration (Either () a) (Either () b)
-> ProEnumeration (Maybe a) (Maybe b))
-> ProEnumeration (Either () a) (Either () b)
-> ProEnumeration (Maybe a) (Maybe b)
forall a b. (a -> b) -> a -> b
$
ProEnumeration () ()
forall a. ProEnumeration a ()
unit ProEnumeration () ()
-> ProEnumeration a b -> ProEnumeration (Either () a) (Either () b)
forall a1 b1 a2 b2.
ProEnumeration a1 b1
-> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
<+> ProEnumeration a b
p
eitherOf :: ProEnumeration a1 b1 -> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
eitherOf :: forall a1 b1 a2 b2.
ProEnumeration a1 b1
-> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
eitherOf = ProEnumeration a1 b1
-> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
forall a1 b1 a2 b2.
ProEnumeration a1 b1
-> ProEnumeration a2 b2
-> ProEnumeration (Either a1 a2) (Either b1 b2)
(<+>)
listOf :: ProEnumeration a b -> ProEnumeration [a] [b]
listOf :: forall a b. ProEnumeration a b -> ProEnumeration [a] [b]
listOf ProEnumeration a b
p = CoEnumeration [a] -> Enumeration [b] -> ProEnumeration [a] [b]
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration (CoEnumeration a -> CoEnumeration [a]
forall a. CoEnumeration a -> CoEnumeration [a]
C.listOf (ProEnumeration a b -> CoEnumeration a
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a b
p)) (Enumeration b -> Enumeration [b]
forall a. Enumeration a -> Enumeration [a]
E.listOf (ProEnumeration a b -> Enumeration b
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a b
p))
finiteSubsetOf :: ProEnumeration a b -> ProEnumeration [a] [b]
finiteSubsetOf :: forall a b. ProEnumeration a b -> ProEnumeration [a] [b]
finiteSubsetOf ProEnumeration a b
p =
CoEnumeration [a] -> Enumeration [b] -> ProEnumeration [a] [b]
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration (CoEnumeration a -> CoEnumeration [a]
forall a. CoEnumeration a -> CoEnumeration [a]
C.finiteSubsetOf (ProEnumeration a b -> CoEnumeration a
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a b
p)) (Enumeration b -> Enumeration [b]
forall a. Enumeration a -> Enumeration [a]
E.finiteSubsetOf (ProEnumeration a b -> Enumeration b
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a b
p))
enumerateP :: CoEnumeration a -> Enumeration b -> Enumeration (ProEnumeration a b)
enumerateP :: forall a b.
CoEnumeration a
-> Enumeration b -> Enumeration (ProEnumeration a b)
enumerateP CoEnumeration a
a Enumeration b
b = case (CoEnumeration a -> Cardinality
forall a. CoEnumeration a -> Cardinality
C.card CoEnumeration a
a, Enumeration b -> Cardinality
forall a. Enumeration a -> Cardinality
E.card Enumeration b
b) of
(Cardinality
0, Cardinality
_) -> ProEnumeration a b -> Enumeration (ProEnumeration a b)
forall a. a -> Enumeration a
E.singleton (CoEnumeration a -> Enumeration b -> ProEnumeration a b
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
a Enumeration b
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
Ap.empty)
(Cardinality
_, Cardinality
1) -> ProEnumeration a b -> Enumeration (ProEnumeration a b)
forall a. a -> Enumeration a
E.singleton (CoEnumeration a -> Enumeration b -> ProEnumeration a b
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
forall a. CoEnumeration a
C.unit Enumeration b
b)
(Finite Integer
k,Cardinality
_) -> CoEnumeration a -> Enumeration b -> ProEnumeration a b
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration CoEnumeration a
a (Enumeration b -> ProEnumeration a b)
-> Enumeration (Enumeration b) -> Enumeration (ProEnumeration a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Enumeration b -> Enumeration (Enumeration b)
forall a. Int -> Enumeration a -> Enumeration (Enumeration a)
E.finiteEnumerationOf (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
k) Enumeration b
b
(Cardinality
Infinite,Cardinality
_) -> [Char] -> Enumeration (ProEnumeration a b)
forall a. HasCallStack => [Char] -> a
error [Char]
"infinite domain"
coenumerateP :: Enumeration a -> CoEnumeration b -> CoEnumeration (a -> b)
coenumerateP :: forall a b.
Enumeration a -> CoEnumeration b -> CoEnumeration (a -> b)
coenumerateP Enumeration a
a CoEnumeration b
b = case (Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
E.card Enumeration a
a, CoEnumeration b -> Cardinality
forall a. CoEnumeration a -> Cardinality
C.card CoEnumeration b
b) of
(Cardinality
0, Cardinality
_) -> CoEnumeration (a -> b)
forall a. CoEnumeration a
C.unit
(Cardinality
_, Cardinality
1) -> CoEnumeration (a -> b)
forall a. CoEnumeration a
C.unit
(Finite Integer
k,Cardinality
_) -> ((a -> b) -> Integer -> b)
-> CoEnumeration (Integer -> b) -> CoEnumeration (a -> b)
forall a' a. (a' -> a) -> CoEnumeration a -> CoEnumeration a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap (\a -> b
f -> a -> b
f (a -> b) -> (Integer -> a) -> Integer -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select Enumeration a
a) (CoEnumeration (Integer -> b) -> CoEnumeration (a -> b))
-> CoEnumeration (Integer -> b) -> CoEnumeration (a -> b)
forall a b. (a -> b) -> a -> b
$ Integer -> CoEnumeration b -> CoEnumeration (Integer -> b)
forall a.
Integer -> CoEnumeration a -> CoEnumeration (Integer -> a)
C.finiteFunctionOf Integer
k CoEnumeration b
b
(Cardinality
Infinite,Cardinality
_) -> [Char] -> CoEnumeration (a -> b)
forall a. HasCallStack => [Char] -> a
error [Char]
"infinite domain"
proenumerationOf
:: ProEnumeration a a'
-> ProEnumeration b b'
-> ProEnumeration (a' -> b) (ProEnumeration a b')
proenumerationOf :: forall a a' b b'.
ProEnumeration a a'
-> ProEnumeration b b'
-> ProEnumeration (a' -> b) (ProEnumeration a b')
proenumerationOf ProEnumeration a a'
a ProEnumeration b b'
b
= CoEnumeration (a' -> b)
-> Enumeration (ProEnumeration a b')
-> ProEnumeration (a' -> b) (ProEnumeration a b')
forall a b. CoEnumeration a -> Enumeration b -> ProEnumeration a b
mkProEnumeration
(Enumeration a' -> CoEnumeration b -> CoEnumeration (a' -> b)
forall a b.
Enumeration a -> CoEnumeration b -> CoEnumeration (a -> b)
coenumerateP (ProEnumeration a a' -> Enumeration a'
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration a a'
a) (ProEnumeration b b' -> CoEnumeration b
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration b b'
b))
(CoEnumeration a
-> Enumeration b' -> Enumeration (ProEnumeration a b')
forall a b.
CoEnumeration a
-> Enumeration b -> Enumeration (ProEnumeration a b)
enumerateP (ProEnumeration a a' -> CoEnumeration a
forall a b. ProEnumeration a b -> CoEnumeration a
baseCoEnum ProEnumeration a a'
a) (ProEnumeration b b' -> Enumeration b'
forall a b. ProEnumeration a b -> Enumeration b
baseEnum ProEnumeration b b'
b))
finiteFunctionOf
:: Integer -> ProEnumeration a b -> ProEnumeration (Integer -> a) (Integer -> b)
finiteFunctionOf :: forall a b.
Integer
-> ProEnumeration a b
-> ProEnumeration (Integer -> a) (Integer -> b)
finiteFunctionOf Integer
k ProEnumeration a b
p = ProEnumeration Integer Integer
-> ProEnumeration a b
-> ProEnumeration (Integer -> a) (ProEnumeration Integer b)
forall a a' b b'.
ProEnumeration a a'
-> ProEnumeration b b'
-> ProEnumeration (a' -> b) (ProEnumeration a b')
proenumerationOf (Integer -> ProEnumeration Integer Integer
modulo Integer
k) ProEnumeration a b
p ProEnumeration (Integer -> a) (ProEnumeration Integer b)
-> (ProEnumeration Integer b -> Integer -> b)
-> ProEnumeration (Integer -> a) (Integer -> b)
forall a b b'.
ProEnumeration a b -> (b -> b') -> ProEnumeration a b'
@. ProEnumeration Integer b -> Integer -> b
forall a b. ProEnumeration a b -> Integer -> b
select