{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Data.Enumeration
(
Enumeration
, mkEnumeration
, Cardinality(..), card
, Index, select
, isFinite
, enumerate
, unit
, singleton
, always
, finite
, finiteList
, boundedEnum
, nat
, int
, cw
, rat
, takeE
, dropE
, infinite
, zipE, zipWithE
, (<+>)
, (><)
, interleave
, maybeOf
, eitherOf
, listOf
, finiteSubsetOf
, finiteEnumerationOf
, diagonal
) where
import Control.Applicative
import Data.Bits ((.&.))
import Data.Ratio
import Data.Tuple (swap)
import GHC.Base (Int (I#))
import GHC.Integer.Logarithms (integerLog2#)
data Cardinality = Finite !Integer | Infinite
deriving (Int -> Cardinality -> ShowS
[Cardinality] -> ShowS
Cardinality -> String
(Int -> Cardinality -> ShowS)
-> (Cardinality -> String)
-> ([Cardinality] -> ShowS)
-> Show Cardinality
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Cardinality -> ShowS
showsPrec :: Int -> Cardinality -> ShowS
$cshow :: Cardinality -> String
show :: Cardinality -> String
$cshowList :: [Cardinality] -> ShowS
showList :: [Cardinality] -> ShowS
Show, Cardinality -> Cardinality -> Bool
(Cardinality -> Cardinality -> Bool)
-> (Cardinality -> Cardinality -> Bool) -> Eq Cardinality
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Cardinality -> Cardinality -> Bool
== :: Cardinality -> Cardinality -> Bool
$c/= :: Cardinality -> Cardinality -> Bool
/= :: Cardinality -> Cardinality -> Bool
Eq, Eq Cardinality
Eq Cardinality =>
(Cardinality -> Cardinality -> Ordering)
-> (Cardinality -> Cardinality -> Bool)
-> (Cardinality -> Cardinality -> Bool)
-> (Cardinality -> Cardinality -> Bool)
-> (Cardinality -> Cardinality -> Bool)
-> (Cardinality -> Cardinality -> Cardinality)
-> (Cardinality -> Cardinality -> Cardinality)
-> Ord Cardinality
Cardinality -> Cardinality -> Bool
Cardinality -> Cardinality -> Ordering
Cardinality -> Cardinality -> Cardinality
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Cardinality -> Cardinality -> Ordering
compare :: Cardinality -> Cardinality -> Ordering
$c< :: Cardinality -> Cardinality -> Bool
< :: Cardinality -> Cardinality -> Bool
$c<= :: Cardinality -> Cardinality -> Bool
<= :: Cardinality -> Cardinality -> Bool
$c> :: Cardinality -> Cardinality -> Bool
> :: Cardinality -> Cardinality -> Bool
$c>= :: Cardinality -> Cardinality -> Bool
>= :: Cardinality -> Cardinality -> Bool
$cmax :: Cardinality -> Cardinality -> Cardinality
max :: Cardinality -> Cardinality -> Cardinality
$cmin :: Cardinality -> Cardinality -> Cardinality
min :: Cardinality -> Cardinality -> Cardinality
Ord)
instance Num Cardinality where
fromInteger :: Integer -> Cardinality
fromInteger = Integer -> Cardinality
Finite
Cardinality
Infinite + :: Cardinality -> Cardinality -> Cardinality
+ Cardinality
_ = Cardinality
Infinite
Cardinality
_ + Cardinality
Infinite = Cardinality
Infinite
Finite Integer
a + Finite Integer
b = Integer -> Cardinality
Finite (Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
b)
Finite Integer
0 * :: Cardinality -> Cardinality -> Cardinality
* Cardinality
_ = Integer -> Cardinality
Finite Integer
0
Cardinality
_ * Finite Integer
0 = Integer -> Cardinality
Finite Integer
0
Cardinality
Infinite * Cardinality
_ = Cardinality
Infinite
Cardinality
_ * Cardinality
Infinite = Cardinality
Infinite
Finite Integer
a * Finite Integer
b = Integer -> Cardinality
Finite (Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
b)
Finite Integer
a - :: Cardinality -> Cardinality -> Cardinality
- Finite Integer
b = Integer -> Cardinality
Finite (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
0 (Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
b))
Cardinality
_ - Cardinality
Infinite = Integer -> Cardinality
Finite Integer
0
Cardinality
_ - Cardinality
_ = Cardinality
Infinite
negate :: Cardinality -> Cardinality
negate = String -> Cardinality -> Cardinality
forall a. HasCallStack => String -> a
error String
"Can't negate Cardinality"
signum :: Cardinality -> Cardinality
signum = String -> Cardinality -> Cardinality
forall a. HasCallStack => String -> a
error String
"No signum for Cardinality"
abs :: Cardinality -> Cardinality
abs = String -> Cardinality -> Cardinality
forall a. HasCallStack => String -> a
error String
"No abs for Cardinality"
type Index = Integer
data Enumeration a = Enumeration
{
forall a. Enumeration a -> Cardinality
card :: Cardinality
, forall a. Enumeration a -> Integer -> a
select :: Index -> a
}
deriving (forall a b. (a -> b) -> Enumeration a -> Enumeration b)
-> (forall a b. a -> Enumeration b -> Enumeration a)
-> Functor Enumeration
forall a b. a -> Enumeration b -> Enumeration a
forall a b. (a -> b) -> Enumeration a -> Enumeration 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 b. (a -> b) -> Enumeration a -> Enumeration b
fmap :: forall a b. (a -> b) -> Enumeration a -> Enumeration b
$c<$ :: forall a b. a -> Enumeration b -> Enumeration a
<$ :: forall a b. a -> Enumeration b -> Enumeration a
Functor
mkEnumeration :: Cardinality -> (Index -> a) -> Enumeration a
mkEnumeration :: forall a. Cardinality -> (Integer -> a) -> Enumeration a
mkEnumeration = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration
instance Applicative Enumeration where
pure :: forall a. a -> Enumeration a
pure = a -> Enumeration a
forall a. a -> Enumeration a
singleton
Enumeration (a -> b)
f <*> :: forall a b. Enumeration (a -> b) -> Enumeration a -> Enumeration b
<*> Enumeration a
x = ((a -> b) -> a -> b) -> (a -> b, a) -> b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
($) ((a -> b, a) -> b) -> Enumeration (a -> b, a) -> Enumeration b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Enumeration (a -> b)
f Enumeration (a -> b) -> Enumeration a -> Enumeration (a -> b, a)
forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
>< Enumeration a
x)
instance Alternative Enumeration where
empty :: forall a. Enumeration a
empty = Enumeration a
forall a. Enumeration a
void
<|> :: forall a. Enumeration a -> Enumeration a -> Enumeration a
(<|>) = Enumeration a -> Enumeration a -> Enumeration a
forall a. Enumeration a -> Enumeration a -> Enumeration a
(<+>)
isFinite :: Enumeration a -> Bool
isFinite :: forall a. Enumeration a -> Bool
isFinite (Enumeration (Finite Integer
_) Integer -> a
_) = Bool
True
isFinite Enumeration a
_ = Bool
False
enumerate :: Enumeration a -> [a]
enumerate :: forall a. Enumeration a -> [a]
enumerate Enumeration a
e = (Integer -> a) -> [Integer] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e) ([Integer] -> [a]) -> [Integer] -> [a]
forall a b. (a -> b) -> a -> b
$
case Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e of
Cardinality
Infinite -> [Integer
0 ..]
Finite Integer
c -> [Integer
0 .. Integer
cInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1]
void :: Enumeration a
void :: forall a. Enumeration a
void = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
0 (String -> Integer -> a
forall a. HasCallStack => String -> a
error String
"select void")
unit :: Enumeration ()
unit :: Enumeration ()
unit = Enumeration
{ card :: Cardinality
card = Cardinality
1
, select :: Integer -> ()
select = () -> Integer -> ()
forall a b. a -> b -> a
const ()
}
singleton :: a -> Enumeration a
singleton :: forall a. a -> Enumeration a
singleton a
a = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
1 (a -> Integer -> a
forall a b. a -> b -> a
const a
a)
always :: a -> Enumeration a
always :: forall a. a -> Enumeration a
always a
a = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
Infinite (a -> Integer -> a
forall a b. a -> b -> a
const a
a)
finite :: Integer -> Enumeration Integer
finite :: Integer -> Enumeration Integer
finite Integer
n = Cardinality -> (Integer -> Integer) -> Enumeration Integer
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration (Integer -> Cardinality
Finite Integer
n) Integer -> Integer
forall a. a -> a
id
finiteList :: [a] -> Enumeration a
finiteList :: forall a. [a] -> Enumeration a
finiteList [a]
as = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration (Integer -> Cardinality
Finite (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Int -> Integer
forall a b. (a -> b) -> a -> b
$ [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
as)) (\Integer
k -> [a]
as [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
k)
boundedEnum :: forall a. (Enum a, Bounded a) => Enumeration a
boundedEnum :: forall a. (Enum a, Bounded a) => Enumeration a
boundedEnum = Enumeration
{ card :: Cardinality
card = Integer -> Cardinality
Finite (Integer
hi Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
, select :: Integer -> a
select = Int -> a
forall a. Enum a => Int -> a
toEnum (Int -> a) -> (Integer -> Int) -> Integer -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int) -> (Integer -> Integer) -> Integer -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
lo)
}
where
lo, hi :: 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))
hi :: Integer
hi = 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
maxBound @a))
nat :: Enumeration Integer
nat :: Enumeration Integer
nat = Cardinality -> (Integer -> Integer) -> Enumeration Integer
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
Infinite Integer -> Integer
forall a. a -> a
id
int :: Enumeration Integer
int :: Enumeration Integer
int = Integer -> Integer
forall a. Num a => a -> a
negate (Integer -> Integer) -> Enumeration Integer -> Enumeration Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration Integer
nat Enumeration Integer -> Enumeration Integer -> Enumeration Integer
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Integer -> Enumeration Integer -> Enumeration Integer
forall a. Integer -> Enumeration a -> Enumeration a
dropE Integer
1 Enumeration Integer
nat
cw :: Enumeration Rational
cw :: Enumeration Rational
cw = Enumeration { card :: Cardinality
card = Cardinality
Infinite, select :: Integer -> Rational
select = (Integer -> Integer -> Rational) -> (Integer, Integer) -> Rational
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
(%) ((Integer, Integer) -> Rational)
-> (Integer -> (Integer, Integer)) -> Integer -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> (Integer, Integer)
forall {t} {b}. (Num b, Integral t) => t -> (b, b)
go (Integer -> (Integer, Integer))
-> (Integer -> Integer) -> Integer -> (Integer, Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer
forall a. Enum a => a -> a
succ }
where
go :: t -> (b, b)
go t
1 = (b
1,b
1)
go t
n
| t -> Bool
forall a. Integral a => a -> Bool
even t
n = (b, b) -> (b, b)
forall {b}. Num b => (b, b) -> (b, b)
left (t -> (b, b)
go (t
n t -> t -> t
forall a. Integral a => a -> a -> a
`div` t
2))
| Bool
otherwise = (b, b) -> (b, b)
forall {b}. Num b => (b, b) -> (b, b)
right (t -> (b, b)
go (t
n t -> t -> t
forall a. Integral a => a -> a -> a
`div` t
2))
left :: (b, b) -> (b, b)
left (!b
a, !b
b) = (b
a, b
ab -> b -> b
forall a. Num a => a -> a -> a
+b
b)
right :: (b, b) -> (b, b)
right (!b
a, !b
b) = (b
ab -> b -> b
forall a. Num a => a -> a -> a
+b
b, b
b)
rat :: Enumeration Rational
rat :: Enumeration Rational
rat = Rational -> Enumeration Rational
forall a. a -> Enumeration a
singleton Rational
0 Enumeration Rational
-> Enumeration Rational -> Enumeration Rational
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Enumeration Rational
cw Enumeration Rational
-> Enumeration Rational -> Enumeration Rational
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Rational -> Rational
forall a. Num a => a -> a
negate (Rational -> Rational)
-> Enumeration Rational -> Enumeration Rational
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration Rational
cw)
takeE :: Integer -> Enumeration a -> Enumeration a
takeE :: forall a. Integer -> Enumeration a -> Enumeration a
takeE Integer
k Enumeration a
e
| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 = Enumeration a
forall a. Enumeration a
void
| Integer -> Cardinality
Finite Integer
k Cardinality -> Cardinality -> Bool
forall a. Ord a => a -> a -> Bool
>= Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e = Enumeration a
e
| Bool
otherwise = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration (Integer -> Cardinality
Finite Integer
k) (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e)
dropE :: Integer -> Enumeration a -> Enumeration a
dropE :: forall a. Integer -> Enumeration a -> Enumeration a
dropE Integer
k Enumeration a
e
| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 = Enumeration a
e
| Integer -> Cardinality
Finite Integer
k Cardinality -> Cardinality -> Bool
forall a. Ord a => a -> a -> Bool
>= Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e = Enumeration a
forall a. Enumeration a
void
| Bool
otherwise = Enumeration
{ card :: Cardinality
card = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e Cardinality -> Cardinality -> Cardinality
forall a. Num a => a -> a -> a
- Integer -> Cardinality
Finite Integer
k, select :: Integer -> a
select = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e (Integer -> a) -> (Integer -> Integer) -> Integer -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
k) }
infinite :: Enumeration a -> Enumeration a
infinite :: forall a. Enumeration a -> Enumeration a
infinite (Enumeration Cardinality
_ Integer -> a
s) = Cardinality -> (Integer -> a) -> Enumeration a
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
Infinite Integer -> a
s
interleave :: Enumeration (Enumeration a) -> Enumeration a
interleave :: forall a. Enumeration (Enumeration a) -> Enumeration a
interleave Enumeration (Enumeration a)
e = Enumeration
{ card :: Cardinality
card = Cardinality
Infinite
, select :: Integer -> a
select = \Integer
k ->
let (Integer
i,Integer
j) = case Enumeration (Enumeration a) -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration (Enumeration 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)
diagonal Integer
k
in Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select (Enumeration (Enumeration a) -> Integer -> Enumeration a
forall a. Enumeration a -> Integer -> a
select Enumeration (Enumeration a)
e Integer
j) Integer
i
}
zipE :: Enumeration a -> Enumeration b -> Enumeration (a,b)
zipE :: forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
zipE = (a -> b -> (a, b))
-> Enumeration a -> Enumeration b -> Enumeration (a, b)
forall a b c.
(a -> b -> c) -> Enumeration a -> Enumeration b -> Enumeration c
zipWithE (,)
zipWithE :: (a -> b -> c) -> Enumeration a -> Enumeration b -> Enumeration c
zipWithE :: forall a b c.
(a -> b -> c) -> Enumeration a -> Enumeration b -> Enumeration c
zipWithE a -> b -> c
f Enumeration a
e1 Enumeration b
e2 =
Cardinality -> (Integer -> c) -> Enumeration c
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration (Cardinality -> Cardinality -> Cardinality
forall a. Ord a => a -> a -> a
min (Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e1) (Enumeration b -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration b
e2)) (\Integer
k -> a -> b -> c
f (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e1 Integer
k) (Enumeration b -> Integer -> b
forall a. Enumeration a -> Integer -> a
select Enumeration b
e2 Integer
k))
(<+>) :: Enumeration a -> Enumeration a -> Enumeration a
Enumeration a
e1 <+> :: forall a. Enumeration a -> Enumeration a -> Enumeration a
<+> Enumeration a
e2 = case (Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e1, Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e2) of
(Finite Integer
0, Cardinality
_) -> Enumeration a
e2
(Finite Integer
k1, Cardinality
_) -> Enumeration
{ card :: Cardinality
card = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e1 Cardinality -> Cardinality -> Cardinality
forall a. Num a => a -> a -> a
+ Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e2
, select :: Integer -> a
select = \Integer
k -> if Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
k1 then Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e1 Integer
k else Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e2 (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
k1)
}
(Cardinality
_, Finite Integer
_) -> Enumeration a
e2 Enumeration a -> Enumeration a -> Enumeration a
forall a. Enumeration a -> Enumeration a -> Enumeration a
<+> Enumeration a
e1
(Cardinality, Cardinality)
_ -> Enumeration (Enumeration a) -> Enumeration a
forall a. Enumeration (Enumeration a) -> Enumeration a
interleave (Cardinality
-> (Integer -> Enumeration a) -> Enumeration (Enumeration a)
forall a. Cardinality -> (Integer -> a) -> Enumeration a
Enumeration Cardinality
2 (\case {Integer
0 -> Enumeration a
e1; Integer
1 -> Enumeration a
e2}))
diagonal :: Integer -> (Integer, Integer)
diagonal :: Integer -> (Integer, Integer)
diagonal Integer
k = (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
t, Integer
d Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
t))
where
d :: Integer
d = (Integer -> Integer
integerSqrt (Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
8Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
k) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
t :: Integer
t = Integer
dInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*(Integer
dInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
(><) :: Enumeration a -> Enumeration b -> Enumeration (a,b)
Enumeration a
e1 >< :: forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
>< Enumeration b
e2 = case (Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e1, Enumeration b -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration b
e2) of
(Cardinality
_, Finite Integer
k2) -> Enumeration
{ card :: Cardinality
card = Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
e1 Cardinality -> Cardinality -> Cardinality
forall a. Num a => a -> a -> a
* Enumeration b -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration b
e2
, select :: Integer -> (a, b)
select = \Integer
k -> let (Integer
i,Integer
j) = Integer
k Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
`divMod` Integer
k2 in (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e1 Integer
i, Enumeration b -> Integer -> b
forall a. Enumeration a -> Integer -> a
select Enumeration b
e2 Integer
j)
}
(Finite Integer
_, Cardinality
_) -> (b, a) -> (a, b)
forall a b. (a, b) -> (b, a)
swap ((b, a) -> (a, b)) -> Enumeration (b, a) -> Enumeration (a, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Enumeration b
e2 Enumeration b -> Enumeration a -> Enumeration (b, a)
forall a b. Enumeration a -> Enumeration b -> Enumeration (a, b)
>< Enumeration a
e1)
(Cardinality, Cardinality)
_ -> Enumeration
{ card :: Cardinality
card = Cardinality
Infinite
, select :: Integer -> (a, b)
select = \Integer
k -> let (Integer
i,Integer
j) = Integer -> (Integer, Integer)
diagonal Integer
k in (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
e1 Integer
i, Enumeration b -> Integer -> b
forall a. Enumeration a -> Integer -> a
select Enumeration b
e2 Integer
j)
}
maybeOf :: Enumeration a -> Enumeration (Maybe a)
maybeOf :: forall a. Enumeration a -> Enumeration (Maybe a)
maybeOf Enumeration a
a = Maybe a -> Enumeration (Maybe a)
forall a. a -> Enumeration a
singleton Maybe a
forall a. Maybe a
Nothing Enumeration (Maybe a)
-> Enumeration (Maybe a) -> Enumeration (Maybe a)
forall a. Enumeration a -> Enumeration a -> Enumeration a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Enumeration a -> Enumeration (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration a
a
eitherOf :: Enumeration a -> Enumeration b -> Enumeration (Either a b)
eitherOf :: forall a b.
Enumeration a -> Enumeration b -> Enumeration (Either a b)
eitherOf Enumeration a
a Enumeration b
b = 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
<$> Enumeration 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
<$> Enumeration b
b
listOf :: Enumeration a -> Enumeration [a]
listOf :: forall a. Enumeration a -> Enumeration [a]
listOf Enumeration a
a = case Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
a of
Finite Integer
0 -> [a] -> Enumeration [a]
forall a. a -> Enumeration a
singleton []
Cardinality
_ -> Enumeration [a]
listOfA
where
listOfA :: Enumeration [a]
listOfA = Enumeration [a] -> Enumeration [a]
forall a. Enumeration a -> Enumeration a
infinite (Enumeration [a] -> Enumeration [a])
-> Enumeration [a] -> Enumeration [a]
forall a b. (a -> b) -> a -> b
$ [a] -> Enumeration [a]
forall a. a -> Enumeration a
singleton [] 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
<|> (:) (a -> [a] -> [a]) -> Enumeration a -> Enumeration ([a] -> [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration a
a Enumeration ([a] -> [a]) -> Enumeration [a] -> Enumeration [a]
forall a b. Enumeration (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Enumeration [a]
listOfA
finiteSubsetOf :: Enumeration a -> Enumeration [a]
finiteSubsetOf :: forall a. Enumeration a -> Enumeration [a]
finiteSubsetOf Enumeration a
as = Integer -> [a]
pick (Integer -> [a]) -> Enumeration Integer -> Enumeration [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration Integer
bitstrings
where
bitstrings :: Enumeration Integer
bitstrings = case Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
as of
Cardinality
Infinite -> Enumeration Integer
nat
Finite Integer
k -> Integer -> Enumeration Integer
finite (Integer
2Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
k)
pick :: Integer -> [a]
pick Integer
0 = []
pick Integer
n = Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
as (Integer -> Integer
integerLog2 Integer
l) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Integer -> [a]
pick (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
l)
where
l :: Integer
l = Integer -> Integer
lsb Integer
n
lsb :: Integer -> Integer
lsb :: Integer -> Integer
lsb Integer
n = Integer
n Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.&. (-Integer
n)
integerLog2 :: Integer -> Integer
integerLog2 :: Integer -> Integer
integerLog2 Integer
n = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# (Integer -> Int#
integerLog2# Integer
n))
finiteEnumerationOf :: Int -> Enumeration a -> Enumeration (Enumeration a)
finiteEnumerationOf :: forall a. Int -> Enumeration a -> Enumeration (Enumeration a)
finiteEnumerationOf Int
0 Enumeration a
_ = Enumeration a -> Enumeration (Enumeration a)
forall a. a -> Enumeration a
singleton Enumeration a
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
empty
finiteEnumerationOf Int
n Enumeration a
a = case Enumeration a -> Cardinality
forall a. Enumeration a -> Cardinality
card Enumeration a
a of
Finite Integer
k -> Integer -> Integer -> Enumeration a
selectEnum Integer
k (Integer -> Enumeration a)
-> Enumeration Integer -> Enumeration (Enumeration a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Integer -> Enumeration Integer
finite (Integer
kInteger -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Int
n)
Cardinality
Infinite -> (Enumeration a
-> Enumeration (Enumeration a) -> Enumeration (Enumeration a))
-> Enumeration (Enumeration a)
-> [Enumeration a]
-> Enumeration (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 Enumeration a
-> Enumeration (Enumeration a) -> Enumeration (Enumeration a)
forall a.
Enumeration a
-> Enumeration (Enumeration a) -> Enumeration (Enumeration a)
cons (Enumeration a -> Enumeration (Enumeration a)
forall a. a -> Enumeration a
singleton Enumeration a
forall a. Enumeration a
forall (f :: * -> *) a. Alternative f => f a
empty) (Int -> Enumeration a -> [Enumeration a]
forall a. Int -> a -> [a]
replicate Int
n Enumeration a
a)
where
selectEnum :: Integer -> Integer -> Enumeration a
selectEnum Integer
k = (Integer -> a) -> Enumeration Integer -> Enumeration a
forall a b. (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Enumeration a -> Integer -> a
forall a. Enumeration a -> Integer -> a
select Enumeration a
a) (Enumeration Integer -> Enumeration a)
-> (Integer -> Enumeration Integer) -> Integer -> Enumeration a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Integer] -> Enumeration Integer
forall a. [a] -> Enumeration a
finiteList ([Integer] -> Enumeration Integer)
-> (Integer -> [Integer]) -> Integer -> Enumeration Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Integer] -> [Integer]
forall a. [a] -> [a]
reverse ([Integer] -> [Integer])
-> (Integer -> [Integer]) -> Integer -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Integer] -> [Integer]
forall a. Int -> [a] -> [a]
take Int
n ([Integer] -> [Integer])
-> (Integer -> [Integer]) -> Integer -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> [Integer]
forall {t}. Integral t => t -> t -> [t]
toBase Integer
k
toBase :: t -> t -> [t]
toBase t
_ t
0 = t -> [t]
forall a. a -> [a]
repeat t
0
toBase t
k t
n = t
n t -> t -> t
forall a. Integral a => a -> a -> a
`mod` t
k t -> [t] -> [t]
forall a. a -> [a] -> [a]
: t -> t -> [t]
toBase t
k (t
n t -> t -> t
forall a. Integral a => a -> a -> a
`div` t
k)
cons :: Enumeration a -> Enumeration (Enumeration a) -> Enumeration (Enumeration a)
cons :: forall a.
Enumeration a
-> Enumeration (Enumeration a) -> Enumeration (Enumeration a)
cons Enumeration a
a Enumeration (Enumeration a)
as = 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 -> Enumeration a -> Enumeration a)
-> Enumeration (Enumeration a)
-> Enumeration (Enumeration a -> Enumeration a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> Enumeration a
forall a. a -> Enumeration a
singleton (a -> Enumeration a)
-> Enumeration a -> Enumeration (Enumeration a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Enumeration a
a) Enumeration (Enumeration a -> Enumeration a)
-> Enumeration (Enumeration a) -> Enumeration (Enumeration a)
forall a b. Enumeration (a -> b) -> Enumeration a -> Enumeration b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Enumeration (Enumeration a)
as
integerSqrt :: Integer -> Integer
integerSqrt :: Integer -> Integer
integerSqrt Integer
0 = Integer
0
integerSqrt Integer
1 = Integer
1
integerSqrt Integer
n =
let twopows :: [Integer]
twopows = (Integer -> Integer) -> Integer -> [Integer]
forall a. (a -> a) -> a -> [a]
iterate (Integer -> Int -> Integer
forall a. Num a => a -> Int -> a
^!Int
2) Integer
2
(Integer
lowerRoot, Integer
lowerN) =
[(Integer, Integer)] -> (Integer, Integer)
forall a. HasCallStack => [a] -> a
last ([(Integer, Integer)] -> (Integer, Integer))
-> [(Integer, Integer)] -> (Integer, Integer)
forall a b. (a -> b) -> a -> b
$ ((Integer, Integer) -> Bool)
-> [(Integer, Integer)] -> [(Integer, Integer)]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile ((Integer
nInteger -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>=) (Integer -> Bool)
-> ((Integer, Integer) -> Integer) -> (Integer, Integer) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer, Integer) -> Integer
forall a b. (a, b) -> b
snd) ([(Integer, Integer)] -> [(Integer, Integer)])
-> [(Integer, Integer)] -> [(Integer, Integer)]
forall a b. (a -> b) -> a -> b
$ [Integer] -> [Integer] -> [(Integer, Integer)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Integer
1Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
:[Integer]
twopows) [Integer]
twopows
newtonStep :: Integer -> Integer
newtonStep Integer
x = Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div Integer
n Integer
x) Integer
2
isRoot :: Integer -> Bool
isRoot Integer
r = Integer
rInteger -> Int -> Integer
forall a. Num a => a -> Int -> a
^!Int
2 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
n Bool -> Bool -> Bool
&& Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< (Integer
rInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1)Integer -> Int -> Integer
forall a. Num a => a -> Int -> a
^!Int
2
initGuess :: Integer
initGuess = Integer -> Integer
integerSqrt (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div Integer
n Integer
lowerN ) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
lowerRoot
in (Integer -> Bool) -> (Integer -> Integer) -> Integer -> Integer
forall a. (a -> Bool) -> (a -> a) -> a -> a
iterUntil Integer -> Bool
isRoot Integer -> Integer
newtonStep Integer
initGuess
iterUntil :: (a -> Bool) -> (a -> a) -> a -> a
iterUntil :: forall a. (a -> Bool) -> (a -> a) -> a -> a
iterUntil a -> Bool
p a -> a
f a
a
| a -> Bool
p a
a = a
a
| Bool
otherwise = (a -> Bool) -> (a -> a) -> a -> a
forall a. (a -> Bool) -> (a -> a) -> a -> a
iterUntil a -> Bool
p a -> a
f (a -> a
f a
a)
(^!) :: Num a => a -> Int -> a
^! :: forall a. Num a => a -> Int -> a
(^!) a
x Int
n = a
xa -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Int
n