{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Data.Enumeration.Invertible
(
IEnumeration
, Cardinality(..), card
, Index, select, locate
, isFinite
, enumerate
, void
, unit
, singleton
, finite
, finiteList
, boundedEnum
, nat
, int
, cw
, rat
, mapE
, takeE, dropE
, zipE
, infinite
, (<+>)
, (><)
, interleave
, maybeOf
, eitherOf
, listOf
, finiteSubsetOf
, finiteEnumerationOf
, functionOf
, undiagonal
) where
import Control.Applicative (Alternative (..))
import Data.Bits (shiftL, (.|.))
import Data.List (findIndex, foldl')
import Data.Maybe (fromJust)
import Data.Ratio
import Data.Enumeration (Cardinality (..), Enumeration, Index)
import qualified Data.Enumeration as E
data IEnumeration a = IEnumeration
{ forall a. IEnumeration a -> Enumeration a
baseEnum :: Enumeration a
, forall a. IEnumeration a -> a -> Integer
locate :: a -> Index
}
mapE :: (a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE :: forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE a -> b
f b -> a
g (IEnumeration Enumeration a
e a -> Integer
l) = Enumeration b -> (b -> Integer) -> IEnumeration b
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (a -> b
f (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration a
e) (a -> Integer
l (a -> Integer) -> (b -> a) -> b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> a
g)
select :: IEnumeration a -> (Index -> a)
select :: forall a. IEnumeration a -> Integer -> a
select = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select (Enumeration a -> Integer -> a)
-> (IEnumeration a -> Enumeration a)
-> IEnumeration a
-> Integer
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum
card :: IEnumeration a -> Cardinality
card :: forall a. IEnumeration a -> Cardinality
card = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
E.card (Enumeration a -> Cardinality)
-> (IEnumeration a -> Enumeration a)
-> IEnumeration a
-> Cardinality
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum
isFinite :: IEnumeration a -> Bool
isFinite :: forall a. IEnumeration a -> Bool
isFinite (IEnumeration Enumeration a
e a -> Integer
_) = Enumeration a -> Bool
forall a. Enumeration a -> Bool
E.isFinite Enumeration a
e
enumerate :: IEnumeration a -> [a]
enumerate :: forall a. IEnumeration a -> [a]
enumerate IEnumeration a
e = case IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
e of
Cardinality
Infinite -> (Integer -> a) -> [Integer] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (IEnumeration a -> Integer -> a
forall a. IEnumeration a -> Integer -> a
select IEnumeration a
e) [Integer
0 ..]
Finite Integer
c -> (Integer -> a) -> [Integer] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (IEnumeration a -> Integer -> a
forall a. IEnumeration a -> Integer -> a
select IEnumeration a
e) [Integer
0 .. Integer
cInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1]
void :: IEnumeration a
void :: forall a. IEnumeration a
void = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration a
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
empty ([Char] -> a -> Integer
forall a. HasCallStack => [Char] -> a
error [Char]
"locate void")
unit :: IEnumeration ()
unit :: IEnumeration ()
unit = Enumeration () -> (() -> Integer) -> IEnumeration ()
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration ()
E.unit (Integer -> () -> Integer
forall a b. a -> b -> a
const Integer
0)
singleton :: a -> IEnumeration a
singleton :: forall a. a -> IEnumeration a
singleton a
a = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (a -> Enumeration a
forall a. a -> Enumeration a
E.singleton a
a) (Integer -> a -> Integer
forall a b. a -> b -> a
const Integer
0)
finite :: Integer -> IEnumeration Integer
finite :: Integer -> IEnumeration Integer
finite Integer
n = Enumeration Integer -> (Integer -> Integer) -> IEnumeration Integer
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Integer -> Enumeration Integer
E.finite Integer
n) Integer -> Integer
forall a. a -> a
id
finiteList :: Eq a => [a] -> IEnumeration a
finiteList :: forall a. Eq a => [a] -> IEnumeration a
finiteList [a]
as = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration ([a] -> Enumeration a
forall a. [a] -> Enumeration a
E.finiteList [a]
as) a -> Integer
forall {c}. Num c => a -> c
locateFinite
where
locateFinite :: a -> c
locateFinite a
a = Int -> c
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> c) -> (Maybe Int -> Int) -> Maybe Int -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Int -> c) -> Maybe Int -> c
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> [a] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
==a
a) [a]
as
boundedEnum :: forall a. (Enum a, Bounded a) => IEnumeration a
boundedEnum :: forall a. (Enum a, Bounded a) => IEnumeration a
boundedEnum = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration a
forall a. (Enum a, Bounded a) => Enumeration a
E.boundedEnum (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
subtract Integer
lo (Integer -> Integer) -> (a -> Integer) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> (a -> Int) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a. Enum a => a -> Int
fromEnum)
where
lo :: Index
lo :: Integer
lo = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> Int
forall a. Enum a => a -> Int
fromEnum (forall a. Bounded a => a
minBound @a))
nat :: IEnumeration Integer
nat :: IEnumeration Integer
nat = Enumeration Integer -> (Integer -> Integer) -> IEnumeration Integer
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration Integer
E.nat Integer -> Integer
forall a. a -> a
id
int :: IEnumeration Integer
int :: IEnumeration Integer
int = Enumeration Integer -> (Integer -> Integer) -> IEnumeration Integer
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration Integer
E.int Integer -> Integer
forall {a}. (Ord a, Num a) => a -> a
locateInt
where
locateInt :: a -> a
locateInt a
z
| a
z a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 = a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Num a => a -> a
abs a
z
| Bool
otherwise = a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
z a -> a -> a
forall a. Num a => a -> a -> a
- a
1
cw :: IEnumeration Rational
cw :: IEnumeration Rational
cw = Enumeration Rational
-> (Rational -> Integer) -> IEnumeration Rational
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration Enumeration Rational
E.cw (Integer -> Integer
forall a. Enum a => a -> a
pred (Integer -> Integer)
-> (Rational -> Integer) -> Rational -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Integer
forall {b} {a}. (Num b, Num a, Ord b) => Ratio b -> a
locateCW)
where
locateCW :: Ratio b -> a
locateCW Ratio b
r = (b, b) -> a
forall {b} {a}. (Num b, Num a, Ord b) => (b, b) -> a
go (Ratio b -> b
forall a. Ratio a -> a
numerator Ratio b
r, Ratio b -> b
forall a. Ratio a -> a
denominator Ratio b
r)
go :: (b, b) -> a
go (b
1,b
1) = a
1
go (b
a,b
b)
| b
a b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
b = a
2 a -> a -> a
forall a. Num a => a -> a -> a
* (b, b) -> a
go (b
a, b
b b -> b -> b
forall a. Num a => a -> a -> a
- b
a)
| Bool
otherwise = a
1 a -> a -> a
forall a. Num a => a -> a -> a
+ a
2 a -> a -> a
forall a. Num a => a -> a -> a
* (b, b) -> a
go (b
a b -> b -> b
forall a. Num a => a -> a -> a
- b
b, b
b)
rat :: IEnumeration Rational
rat :: IEnumeration Rational
rat = (Either () (Either Rational Rational) -> Rational)
-> (Rational -> Either () (Either Rational Rational))
-> IEnumeration (Either () (Either Rational Rational))
-> IEnumeration Rational
forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE
((() -> Rational)
-> (Either Rational Rational -> Rational)
-> Either () (Either Rational Rational)
-> Rational
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Rational -> () -> Rational
forall a b. a -> b -> a
const Rational
0) ((Rational -> Rational)
-> (Rational -> Rational) -> Either Rational Rational -> Rational
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Rational -> Rational
forall a. a -> a
id Rational -> Rational
forall a. Num a => a -> a
negate))
Rational -> Either () (Either Rational Rational)
forall {b}. (Num b, Ord b) => b -> Either () (Either b b)
unrat
(IEnumeration ()
unit IEnumeration ()
-> IEnumeration (Either Rational Rational)
-> IEnumeration (Either () (Either Rational Rational))
forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
<+> (IEnumeration Rational
cw IEnumeration Rational
-> IEnumeration Rational -> IEnumeration (Either Rational Rational)
forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
<+> IEnumeration Rational
cw))
where
unrat :: b -> Either () (Either b b)
unrat b
0 = () -> Either () (Either b b)
forall a b. a -> Either a b
Left ()
unrat b
r
| b
r b -> b -> Bool
forall a. Ord a => a -> a -> Bool
> b
0 = Either b b -> Either () (Either b b)
forall a b. b -> Either a b
Right (b -> Either b b
forall a b. a -> Either a b
Left b
r)
| Bool
otherwise = Either b b -> Either () (Either b b)
forall a b. b -> Either a b
Right (b -> Either b b
forall a b. b -> Either a b
Right (-b
r))
takeE :: Integer -> IEnumeration a -> IEnumeration a
takeE :: forall a. Integer -> IEnumeration a -> IEnumeration a
takeE Integer
k (IEnumeration Enumeration a
e a -> Integer
l) = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Integer -> Enumeration a -> Enumeration a
forall a. Integer -> Enumeration a -> Enumeration a
E.takeE Integer
k Enumeration a
e) a -> Integer
l
dropE :: Integer -> IEnumeration a -> IEnumeration a
dropE :: forall a. Integer -> IEnumeration a -> IEnumeration a
dropE Integer
k (IEnumeration Enumeration a
e a -> Integer
l) = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Integer -> Enumeration a -> Enumeration a
forall a. Integer -> Enumeration a -> Enumeration a
E.dropE Integer
k Enumeration a
e) (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
subtract (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
0 Integer
k) (Integer -> Integer) -> (a -> Integer) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Integer
l)
infinite :: IEnumeration a -> IEnumeration a
infinite :: forall a. IEnumeration a -> IEnumeration a
infinite (IEnumeration Enumeration a
e a -> Integer
l) = Enumeration a -> (a -> Integer) -> IEnumeration a
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Enumeration a -> Enumeration a
forall a. Enumeration a -> Enumeration a
E.infinite Enumeration a
e) a -> Integer
l
interleave :: IEnumeration (IEnumeration a) -> IEnumeration (Index, a)
interleave :: forall a.
IEnumeration (IEnumeration a) -> IEnumeration (Integer, a)
interleave IEnumeration (IEnumeration a)
e = IEnumeration
{ baseEnum :: Enumeration (Integer, a)
baseEnum = Cardinality
-> (Integer -> (Integer, a)) -> Enumeration (Integer, a)
forall a. Cardinality -> (Integer -> a) -> Enumeration a
E.mkEnumeration Cardinality
Infinite ((Integer -> (Integer, a)) -> Enumeration (Integer, a))
-> (Integer -> (Integer, a)) -> Enumeration (Integer, a)
forall a b. (a -> b) -> a -> b
$ \Integer
k ->
let (Integer
i,Integer
j) = case IEnumeration (IEnumeration a) -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration (IEnumeration a)
e of
Finite Integer
n -> Integer
k Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
`divMod` Integer
n
Cardinality
Infinite -> Integer -> (Integer, Integer)
E.diagonal Integer
k
in (Integer
j, IEnumeration a -> Integer -> a
forall a. IEnumeration a -> Integer -> a
select (IEnumeration (IEnumeration a) -> Integer -> IEnumeration a
forall a. IEnumeration a -> Integer -> a
select IEnumeration (IEnumeration a)
e Integer
j) Integer
i)
, locate :: (Integer, a) -> Integer
locate = \(Integer
j, a
a) ->
let i :: Integer
i = IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate (IEnumeration (IEnumeration a) -> Integer -> IEnumeration a
forall a. IEnumeration a -> Integer -> a
select IEnumeration (IEnumeration a)
e Integer
j) a
a
in case IEnumeration (IEnumeration a) -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration (IEnumeration a)
e of
Finite Integer
n -> Integer
iInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
j
Cardinality
Infinite -> (Integer, Integer) -> Integer
undiagonal (Integer
i,Integer
j)
}
zipE :: IEnumeration a -> IEnumeration b -> IEnumeration (a,b)
zipE :: forall a b. IEnumeration a -> IEnumeration b -> IEnumeration (a, b)
zipE IEnumeration a
ea IEnumeration b
eb = IEnumeration
{ baseEnum :: Enumeration (a, b)
baseEnum = Enumeration a -> Enumeration b -> Enumeration (a, b)
forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
E.zipE (IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
ea) (IEnumeration b -> Enumeration b
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration b
eb)
, locate :: (a, b) -> Integer
locate = IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
ea (a -> Integer) -> ((a, b) -> a) -> (a, b) -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, b) -> a
forall a b. (a, b) -> a
fst
}
(<+>) :: IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
IEnumeration a
a <+> :: forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
<+> IEnumeration b
b = Enumeration (Either a b)
-> (Either a b -> Integer) -> IEnumeration (Either a b)
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (a -> Either a b
forall a b. a -> Either a b
Left (a -> Either a b) -> Enumeration a -> Enumeration (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
a Enumeration (Either a b)
-> Enumeration (Either a b) -> Enumeration (Either a b)
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> Enumeration b -> Enumeration (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IEnumeration b -> Enumeration b
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration b
b) (IEnumeration a -> IEnumeration b -> Either a b -> Integer
forall a b.
IEnumeration a -> IEnumeration b -> Either a b -> Integer
locateEither IEnumeration a
a IEnumeration b
b)
where
locateEither :: IEnumeration a -> IEnumeration b -> (Either a b -> Index)
locateEither :: forall a b.
IEnumeration a -> IEnumeration b -> Either a b -> Integer
locateEither IEnumeration a
a IEnumeration b
b = case (IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
a, IEnumeration b -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration b
b) of
(Finite Integer
k1, Cardinality
_) -> (a -> Integer) -> (b -> Integer) -> Either a b -> Integer
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a) ((Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
k1) (Integer -> Integer) -> (b -> Integer) -> b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b)
(Cardinality
_, Finite Integer
k2) -> (a -> Integer) -> (b -> Integer) -> Either a b -> Integer
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
k2) (Integer -> Integer) -> (a -> Integer) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a) (IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b)
(Cardinality, Cardinality)
_ -> (a -> Integer) -> (b -> Integer) -> Either a b -> Integer
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
2) (Integer -> Integer) -> (a -> Integer) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a) (Integer -> Integer
forall a. Enum a => a -> a
succ (Integer -> Integer) -> (b -> Integer) -> b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
2) (Integer -> Integer) -> (b -> Integer) -> b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b)
undiagonal :: (Integer, Integer) -> Integer
undiagonal :: (Integer, Integer) -> Integer
undiagonal (Integer
r,Integer
c) = (Integer
rInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
c) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
rInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
cInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
r
(><) :: IEnumeration a -> IEnumeration b -> IEnumeration (a,b)
IEnumeration a
a >< :: forall a b. IEnumeration a -> IEnumeration b -> IEnumeration (a, b)
>< IEnumeration b
b = Enumeration (a, b) -> ((a, b) -> Integer) -> IEnumeration (a, b)
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
a Enumeration a -> Enumeration b -> Enumeration (a, b)
forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
E.>< IEnumeration b -> Enumeration b
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration b
b) (IEnumeration a -> IEnumeration b -> (a, b) -> Integer
forall a b. IEnumeration a -> IEnumeration b -> (a, b) -> Integer
locatePair IEnumeration a
a IEnumeration b
b)
where
locatePair :: IEnumeration a -> IEnumeration b -> ((a,b) -> Index)
locatePair :: forall a b. IEnumeration a -> IEnumeration b -> (a, b) -> Integer
locatePair IEnumeration a
a IEnumeration b
b = case (IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
a, IEnumeration b -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration b
b) of
(Cardinality
_, Finite Integer
k2) -> \(a
x,b
y) -> Integer
k2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a a
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b b
y
(Finite Integer
k1, Cardinality
_) -> \(a
x,b
y) -> Integer
k1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b b
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a a
x
(Cardinality, Cardinality)
_ -> \(a
x,b
y) -> (Integer, Integer) -> Integer
undiagonal (IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a a
x, IEnumeration b -> b -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration b
b b
y)
maybeOf :: IEnumeration a -> IEnumeration (Maybe a)
maybeOf :: forall a. IEnumeration a -> IEnumeration (Maybe a)
maybeOf IEnumeration a
a = (Either () a -> Maybe a)
-> (Maybe a -> Either () a)
-> IEnumeration (Either () a)
-> IEnumeration (Maybe a)
forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE ((() -> Maybe a) -> (a -> Maybe a) -> Either () a -> Maybe a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe a -> () -> Maybe a
forall a b. a -> b -> a
const Maybe a
forall a. Maybe a
Nothing) a -> Maybe a
forall a. a -> Maybe a
Just) (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) (IEnumeration ()
unit IEnumeration () -> IEnumeration a -> IEnumeration (Either () a)
forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
<+> IEnumeration a
a)
eitherOf :: IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
eitherOf :: forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
eitherOf = IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
(<+>)
listOf :: IEnumeration a -> IEnumeration [a]
listOf :: forall a. IEnumeration a -> IEnumeration [a]
listOf IEnumeration a
a = case IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
a of
Finite Integer
0 -> [a] -> IEnumeration [a]
forall a. a -> IEnumeration a
singleton []
Cardinality
_ -> IEnumeration [a]
listOfA
where
listOfA :: IEnumeration [a]
listOfA = IEnumeration [a] -> IEnumeration [a]
forall a. IEnumeration a -> IEnumeration a
infinite (IEnumeration [a] -> IEnumeration [a])
-> IEnumeration [a] -> IEnumeration [a]
forall a b. (a -> b) -> a -> b
$
(Either () (a, [a]) -> [a])
-> ([a] -> Either () (a, [a]))
-> IEnumeration (Either () (a, [a]))
-> IEnumeration [a]
forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE ((() -> [a]) -> ((a, [a]) -> [a]) -> Either () (a, [a]) -> [a]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ([a] -> () -> [a]
forall a b. a -> b -> a
const []) ((a -> [a] -> [a]) -> (a, [a]) -> [a]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (:))) [a] -> Either () (a, [a])
forall {a}. [a] -> Either () (a, [a])
uncons (IEnumeration ()
unit IEnumeration ()
-> IEnumeration (a, [a]) -> IEnumeration (Either () (a, [a]))
forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (Either a b)
<+> (IEnumeration a
a IEnumeration a -> IEnumeration [a] -> IEnumeration (a, [a])
forall a b. IEnumeration a -> IEnumeration b -> IEnumeration (a, b)
>< IEnumeration [a]
listOfA))
uncons :: [a] -> Either () (a, [a])
uncons [] = () -> Either () (a, [a])
forall a b. a -> Either a b
Left ()
uncons (a
a:[a]
as) = (a, [a]) -> Either () (a, [a])
forall a b. b -> Either a b
Right (a
a, [a]
as)
finiteSubsetOf :: IEnumeration a -> IEnumeration [a]
finiteSubsetOf :: forall a. IEnumeration a -> IEnumeration [a]
finiteSubsetOf IEnumeration a
a = Enumeration [a] -> ([a] -> Integer) -> IEnumeration [a]
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Enumeration a -> Enumeration [a]
forall a. Enumeration a -> Enumeration [a]
E.finiteSubsetOf (IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
a)) [a] -> Integer
unpick
where
unpick :: [a] -> Integer
unpick = (Integer -> Integer -> Integer) -> Integer -> [Integer] -> Integer
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
(.|.) Integer
0 ([Integer] -> Integer) -> ([a] -> [Integer]) -> [a] -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Integer) -> [a] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map ((Integer
1 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL`) (Int -> Integer) -> (a -> Int) -> a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int) -> (a -> Integer) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a)
finiteEnumerationOf :: Int -> IEnumeration a -> IEnumeration (Enumeration a)
finiteEnumerationOf :: forall a. Int -> IEnumeration a -> IEnumeration (Enumeration a)
finiteEnumerationOf Int
0 IEnumeration a
_ = Enumeration a -> IEnumeration (Enumeration a)
forall a. a -> IEnumeration a
singleton Enumeration a
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
empty
finiteEnumerationOf Int
n IEnumeration a
a = case IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
a of
Finite Integer
k -> Enumeration (Enumeration a)
-> (Enumeration a -> Integer) -> IEnumeration (Enumeration a)
forall a. Enumeration a -> (a -> Integer) -> IEnumeration a
IEnumeration (Int -> Enumeration a -> Enumeration (Enumeration a)
forall a. Int -> Enumeration a -> Enumeration (Enumeration a)
E.finiteEnumerationOf Int
n (IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
a)) (Integer -> Enumeration a -> Integer
locateEnum Integer
k)
Cardinality
Infinite -> (IEnumeration a
-> IEnumeration (Enumeration a) -> IEnumeration (Enumeration a))
-> IEnumeration (Enumeration a)
-> [IEnumeration a]
-> IEnumeration (Enumeration a)
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr IEnumeration a
-> IEnumeration (Enumeration a) -> IEnumeration (Enumeration a)
forall a.
IEnumeration a
-> IEnumeration (Enumeration a) -> IEnumeration (Enumeration a)
prod (Enumeration a -> IEnumeration (Enumeration a)
forall a. a -> IEnumeration a
singleton Enumeration a
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
empty) (Int -> IEnumeration a -> [IEnumeration a]
forall a. Int -> a -> [a]
replicate Int
n IEnumeration a
a)
where
locateEnum :: Integer -> Enumeration a -> Integer
locateEnum Integer
k = Integer -> [Integer] -> Integer
forall {t :: * -> *} {b}. (Foldable t, Num b) => b -> t b -> b
fromBase Integer
k ([Integer] -> Integer)
-> (Enumeration a -> [Integer]) -> Enumeration a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Integer] -> [Integer]
forall a. [a] -> [a]
reverse ([Integer] -> [Integer])
-> (Enumeration a -> [Integer]) -> Enumeration a -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Enumeration Integer -> [Integer]
forall a. Enumeration a -> [a]
E.enumerate (Enumeration Integer -> [Integer])
-> (Enumeration a -> Enumeration Integer)
-> Enumeration a
-> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Integer) -> Enumeration a -> Enumeration Integer
forall a b. (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
a)
fromBase :: b -> t b -> b
fromBase b
k = (b -> b -> b) -> b -> t b -> b
forall a b. (a -> b -> b) -> b -> t a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\b
d b
r -> b
d b -> b -> b
forall a. Num a => a -> a -> a
+ b
kb -> b -> b
forall a. Num a => a -> a -> a
*b
r) b
0
prod :: IEnumeration a -> IEnumeration (Enumeration a) -> IEnumeration (Enumeration a)
prod :: forall a.
IEnumeration a
-> IEnumeration (Enumeration a) -> IEnumeration (Enumeration a)
prod IEnumeration a
a IEnumeration (Enumeration a)
as = ((a, Enumeration a) -> Enumeration a)
-> (Enumeration a -> (a, Enumeration a))
-> IEnumeration (a, Enumeration a)
-> IEnumeration (Enumeration a)
forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE (\(a
a,Enumeration a
e) -> a -> Enumeration a
forall a. a -> Enumeration a
E.singleton a
a Enumeration a -> Enumeration a -> Enumeration a
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Enumeration a
e) (\Enumeration a
e -> (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select Enumeration a
e Integer
0, Integer -> Enumeration a -> Enumeration a
forall a. Integer -> Enumeration a -> Enumeration a
E.dropE Integer
1 Enumeration a
e))
(IEnumeration a
a IEnumeration a
-> IEnumeration (Enumeration a) -> IEnumeration (a, Enumeration a)
forall a b. IEnumeration a -> IEnumeration b -> IEnumeration (a, b)
>< IEnumeration (Enumeration a)
as)
functionOf :: IEnumeration a -> IEnumeration b -> IEnumeration (a -> b)
functionOf :: forall a b.
IEnumeration a -> IEnumeration b -> IEnumeration (a -> b)
functionOf IEnumeration a
as IEnumeration b
bs = case IEnumeration b -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration b
bs of
Finite Integer
1 -> (a -> b) -> IEnumeration (a -> b)
forall a. a -> IEnumeration a
singleton (\a
_ -> IEnumeration b -> Integer -> b
forall a. IEnumeration a -> Integer -> a
select IEnumeration b
bs Integer
0)
Finite Integer
0 -> case IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
as of
Finite Integer
0 -> (a -> b) -> IEnumeration (a -> b)
forall a. a -> IEnumeration a
singleton (\a
_ -> [Char] -> b
forall a. HasCallStack => [Char] -> a
error [Char]
"called function with empty domain")
Cardinality
_ -> IEnumeration (a -> b)
forall a. IEnumeration a
void
Cardinality
_ -> case IEnumeration a -> Cardinality
forall a. IEnumeration a -> Cardinality
card IEnumeration a
as of
Cardinality
Infinite -> [Char] -> IEnumeration (a -> b)
forall a. HasCallStack => [Char] -> a
error [Char]
"functionOf with infinite domain"
Finite Integer
n -> (Enumeration b -> a -> b)
-> ((a -> b) -> Enumeration b)
-> IEnumeration (Enumeration b)
-> IEnumeration (a -> b)
forall a b.
(a -> b) -> (b -> a) -> IEnumeration a -> IEnumeration b
mapE Enumeration b -> a -> b
forall {a}. Enumeration a -> a -> a
toFunc (a -> b) -> Enumeration b
forall {b}. (a -> b) -> Enumeration b
fromFunc (Int -> IEnumeration b -> IEnumeration (Enumeration b)
forall a. Int -> IEnumeration a -> IEnumeration (Enumeration a)
finiteEnumerationOf (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n) IEnumeration b
bs)
where
toFunc :: Enumeration a -> a -> a
toFunc Enumeration a
bTuple a
a = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
E.select Enumeration a
bTuple (IEnumeration a -> a -> Integer
forall a. IEnumeration a -> a -> Integer
locate IEnumeration a
as a
a)
fromFunc :: (a -> b) -> Enumeration b
fromFunc a -> b
f = a -> b
f (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IEnumeration a -> Enumeration a
forall a. IEnumeration a -> Enumeration a
baseEnum IEnumeration a
as