{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
module Data.Universe.Some (
UniverseSome (..),
FiniteSome (..),
) where
import Data.Functor.Sum (Sum (..))
import Data.List (genericLength)
import Data.Some (Some, mapSome, mkSome, foldSome)
import Data.Type.Equality ((:~:) (..))
import Data.Universe.Class (Universe (..), Finite (..))
import Data.Universe.Helpers (Tagged (..), Natural, (+++))
import qualified Data.Some.GADT as G
import qualified Data.Some.Newtype as N
import qualified Data.Some.Church as C
class UniverseSome f where
universeSome :: [Some f]
class UniverseSome f => FiniteSome f where
universeFSome :: [Some f]
universeFSome = universeSome
cardinalitySome :: Tagged (Some f) Natural
cardinalitySome = Tagged (genericLength (universeFSome :: [Some f]))
instance UniverseSome f => Universe (N.Some f) where
universe = map (foldSome N.mkSome) universeSome
instance FiniteSome f => Finite (N.Some f) where
universeF = map (foldSome N.mkSome) universeFSome
cardinality = retagSome cardinalitySome
instance UniverseSome f => Universe (G.Some f) where
universe = map (foldSome G.mkSome) universeSome
instance FiniteSome f => Finite (G.Some f) where
universeF = map (foldSome G.mkSome) universeFSome
cardinality = retagSome cardinalitySome
instance UniverseSome f => Universe (C.Some f) where
universe = map (foldSome C.mkSome) universeSome
instance FiniteSome f => Finite (C.Some f) where
universeF = map (foldSome C.mkSome) universeFSome
cardinality = retagSome cardinalitySome
retagSome :: Tagged (Some f) Natural -> Tagged (some f) Natural
retagSome (Tagged n) = Tagged n
instance UniverseSome ((:~:) a) where
universeSome = [mkSome Refl]
instance FiniteSome ((:~:) a) where
cardinalitySome = 1
instance (UniverseSome f, UniverseSome g) => UniverseSome (Sum f g) where
universeSome = map (mapSome InL) universeSome +++ map (mapSome InR) universeSome
instance (FiniteSome f, FiniteSome g) => FiniteSome (Sum f g) where
universeFSome = map (mapSome InL) universeFSome ++ map (mapSome InR) universeFSome