{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Universe.Instances.Extended (
Universe(..), Finite(..)
) where
import Control.Comonad.Trans.Traced (TracedT (..))
import Data.Functor.Contravariant (Op (..), Predicate (..))
import Data.Functor.Rep (Representable (..), Co (..))
import Data.Map (Map)
import Data.Set (Set)
import Data.Universe.Class (Universe (..), Finite (..))
import Data.Universe.Helpers (retag, Tagged, Natural)
import qualified Data.Map as M
import qualified Data.Set as S
#if MIN_VERSION_base(4,7,0)
import Data.Coerce (coerce)
#endif
instance (Representable f, Finite (Rep f), Ord (Rep f), Universe a)
=> Universe (Co f a)
where universe = map tabulate universe
instance (Representable f, Finite s, Ord s, Finite (Rep f), Ord (Rep f), Universe a)
=> Universe (TracedT s f a)
where universe = map tabulate universe
instance (Universe a, Finite b, Ord b) => Universe (Op a b) where
#if MIN_VERSION_base(4,7,0)
universe = coerce (universe :: [b -> a])
#else
universe = map Op universe
#endif
instance (Finite a, Ord a) => Universe (Predicate a) where
universe = map (Predicate . flip S.member) universe
instance (Representable f, Finite (Rep f), Ord (Rep f), Finite a)
=> Finite (Co f a)
where universeF = map tabulate universeF; cardinality = retag (cardinality :: Tagged (Rep (Co f) -> a) Natural)
instance (Representable f, Finite s, Ord s, Finite (Rep f), Ord (Rep f), Finite a)
=> Finite (TracedT s f a)
where universeF = map tabulate universeF; cardinality = retag (cardinality :: Tagged (Rep (TracedT s f)) Natural)
instance (Finite a, Finite b, Ord b) => Finite (Op a b) where
cardinality = retag (cardinality :: Tagged (b -> a) Natural)
instance (Finite a, Ord a) => Finite (Predicate a) where
cardinality = retag (cardinality :: Tagged (Set a) Natural)