module FP.Core -- Exports {{{ ( module Prelude , module FP.Core , module GHC.Exts , module Data.Char , module Language.Haskell.TH , module Data.Coerce ) where -- }}} -- Imports {{{ import qualified Prelude import Prelude ( Eq(..), Ord(..), Ordering(..) , id, (.), ($), const, flip, curry, uncurry , fst, snd , Bool(..), (||), (&&), not, otherwise , Char, Int, Integer, Double, Rational , Maybe(..) , undefined, seq , IO ) import Data.Text (Text) import GHC.Exts (type Constraint) import qualified Data.Text as Text import qualified Data.Set as Set import qualified Data.Map as Map import Language.Haskell.TH (Q) import Data.Char (isSpace, isAlphaNum, isLetter, isDigit) import Data.Coerce -- }}} -- Precedence {{{ infix 9 ? infixl 9 # infixl 9 #! infixl 9 <@> infixl 9 *@ infixl 9 ^@ infixl 9 ^*@ infixr 9 *. infixr 9 ^. infixr 9 .^ infixr 9 ^^. infixr 9 ^.: infixr 9 ^*. infixr 9 <.> infixr 9 .: infixr 9 ..: infixr 9 :.: infix 7 / infix 7 // infixr 7 * infixr 7 <*> infixr 7 /\ infix 6 - infix 6 \\ infixr 6 + infixr 6 ++ infixr 6 :+: infixr 6 <+> infixr 6 \/ infix 4 ⊑ infix 4 ⊏ infixl 1 >>= infixl 1 >> infixr 1 ~> infixr 0 *$ infixr 0 ^$ infixr 0 ^*$ infixr 0 <$> infixr 0 ~: infixr 0 =: infixr 0 |: -- }}} -- Basic Types {{{ data P a = P data W (c :: Constraint) where W :: (c) => W c with :: W c -> (c => a) -> a ; with W x = x -- }}} ------------- -- Classes -- ------------- -- Constraint {{{ class Universal a instance Universal a class (c1 a, c2 a) => (c1 ::*:: c2) a instance (c1 a, c2 a) => (c1 ::*:: c2) a class (t (u a)) => (t ::.:: u) a instance (t (u a)) => (t ::.:: u) a class c1 ::=>:: c2 where impl :: (c1) => W c2 class Functorial c t where functorial :: (c a) => W (c (t a)) class Bifunctorial c t where bifunctorial :: (c a, c b) => W (c (t a b)) -- }}} -- Conversion {{{ class ToInteger a where toInteger :: a -> Integer class FromInteger a where fromInteger :: Integer -> a class ToInt a where toInt :: a -> Int class FromInt a where fromInt :: Int -> a class ToRational a where toRational :: a -> Rational class FromRational a where fromRational :: Rational -> a class ToDouble a where toDouble :: a -> Double class FromDouble a where fromDouble :: Double -> a class ToString a where toString :: a -> String -- }}} -- Arithmetic {{{ class Peano a where zer :: a suc :: a -> a piter :: (Eq a, Peano a) => (b -> b) -> b -> a -> b piter f i0 x = loop i0 zer where loop i j | j == x = i | otherwise = let i' = f i in i' `seq` loop i' $ suc j piterOn :: (Eq a, Peano a) => a -> b -> (b -> b) -> b piterOn = mirror piter class (Peano a) => Additive a where { zero :: a ; (+) :: a -> a -> a } class (Additive a) => Subtractive a where (-) :: a -> a -> a class (Additive a) => Multiplicative a where { one :: a ; (*) :: a -> a -> a } class (Multiplicative a) => Divisible a where (/) :: a -> a -> a class (Multiplicative a) => TruncateDivisible a where (//) :: a -> a -> a class (TruncateDivisible a,ToInteger a,FromInteger a,ToInt a,FromInt a,ToRational a,ToDouble a) => Integral a class (Divisible a,ToRational a,FromRational a,ToDouble a,FromDouble a,FromInteger a,FromInt a) => Fractional a negate :: (Subtractive a) => a -> a ; negate x = zero - x inverse :: (Divisible a) => a -> a ; inverse x = one / x -- }}} -- PartialOrder {{{ data POrdering = PEQ | PLT | PGT | PUN -- Minimal definition: pcompare OR (⊑) class PartialOrder a where pcompare :: a -> a -> POrdering pcompare x y = case (x ⊑ y, y ⊑ x) of (True , True ) -> PEQ (True , False) -> PLT (False, True ) -> PGT (False, False) -> PUN (⊑) :: a -> a -> Bool x ⊑ y = case pcompare x y of PLT -> True PEQ -> True _ -> False (⊏) :: a -> a -> Bool x ⊏ y = case pcompare x y of PLT -> True _ -> False (⋚) :: (Ord a) => a -> a -> Ordering ; (⋚) = compare (⋈) :: (PartialOrder a) => a -> a -> POrdering ; (⋈) = pcompare (⊒) :: (PartialOrder a) => a -> a -> Bool ; (⊒) = flip (⊑) (⊐) :: (PartialOrder a) => a -> a -> Bool ; (⊐) = flip (⊏) fromOrdering :: Ordering -> POrdering fromOrdering EQ = PEQ fromOrdering LT = PLT fromOrdering GT = PGT discreteOrder :: (Eq a) => a -> a -> POrdering discreteOrder x y = if x == y then PEQ else PUN findMax :: (Iterable a t, PartialOrder b) => (a -> b) -> a -> t -> a findMax p i0 = iterFrom i0 $ \ a i -> if p a ⊐ p i then a else i findMaxFrom :: (Iterable a t, PartialOrder b) => a -> (a -> b) -> t -> a findMaxFrom = flip findMax -- this only terminates if f is monotonic and there are no infinite ascending -- chains for the lattice a poiter :: (PartialOrder a) => (a -> a) -> a -> a poiter f = loop where loop x = let x' = f x in if x' ⊑ x then x else loop x' poiterHistory :: (PartialOrder a) => (a -> a) -> a -> [a] poiterHistory f = loop where loop x = let x' = f x in if x' ⊑ x then [x] else x : loop x' -- }}} -- Category {{{ class Category t where catid :: t a a (<.>) :: t b c -> t a b -> t a c type m ~> n = forall a. m a -> n a type t ~~> u = forall m. t m ~> u m class Morphism a b where morph :: a -> b class Morphism2 m n where morph2 :: m ~> n class Morphism3 t u where morph3 :: t ~~> u class (Morphism a b, Morphism b a) => Isomorphism a b isoto :: (Isomorphism a b) => a -> b ; isoto = morph isofrom :: (Isomorphism a b) => b -> a ; isofrom = morph class (Morphism2 t u, Morphism2 u t) => Isomorphism2 t u isoto2 :: (Isomorphism2 t u) => t ~> u ; isoto2 = morph2 isofrom2 :: (Isomorphism2 t u) => u ~> t ; isofrom2 = morph2 onIso2 :: (Isomorphism2 t u) => (u a -> u b) -> t a -> t b ; onIso2 f = isofrom2 . f . isoto2 class (Morphism3 v w, Morphism3 w v) => Isomorphism3 v w isoto3 :: (Isomorphism3 v w) => v ~~> w ; isoto3 = morph3 isofrom3 :: (Isomorphism3 v w) => w ~~> v ; isofrom3 = morph3 -- }}} -- Monoid {{{ class Monoid a where null :: a (++) :: a -> a -> a iterAppend :: (Monoid a, Eq n, Peano n) => n -> a -> a ; iterAppend n = piterOn n null . (++) concat :: (Iterable a t, Monoid a) => t -> a ; concat = foldr (++) null -- }}} -- Lattice {{{ class Bot a where bot :: a class Join a where (\/) :: a -> a -> a class Top a where top :: a class Meet a where (/\) :: a -> a -> a class Neg a where neg :: a -> a class Difference a where (\\) :: a -> a -> a class (Bot a, Join a) => JoinLattice a class (Top a, Meet a) => MeetLattice a class (JoinLattice a, MeetLattice a) => Lattice a class (Lattice a, Neg a) => NegLattice a joins :: (Iterable a t, JoinLattice a) => t -> a ; joins = iter (\/) bot meets :: (Iterable a t, MeetLattice a) => t -> a ; meets = iter (/\) top collect :: (Join a, PartialOrder a) => (a -> a) -> a -> a collect f = poiter $ \ x -> x \/ f x collectN :: (Join a, PartialOrder a, Eq n, Peano n) => n -> (a -> a) -> a -> a collectN n f x0 = piterOn n x0 $ \ x -> x \/ f x collectHistory :: (Join a, PartialOrder a) => (a -> a) -> a -> [a] collectHistory f = poiterHistory $ \ x -> x \/ f x diffs :: forall a. (JoinLattice a, Difference a) => [a] -> [a] diffs = loop bot where loop :: a -> [a] -> [a] loop _ [] = [] loop accum (x:xs) = (x \\ accum) : loop (x \/ accum) xs collectDiffs :: (PartialOrder a, JoinLattice a, Difference a) => (a -> a) -> a -> [a] collectDiffs f = diffs . collectHistory f -- }}} -- Functors {{{ class Commute t u where commute :: t (u a) -> u (t a) class Unit (t :: * -> *) where unit :: a -> t a class Functor (t :: * -> *) where map :: (a -> b) -> (t a -> t b) mapOn :: (Functor t) => t a -> (a -> b) -> t b ; mapOn = flip map (^@) :: (Functor t) => (a -> b) -> t a -> t b ; (^@) = map (^$) :: (Functor t) => (a -> b) -> t a -> t b ; (^$) = map (^.) :: (Functor t) => (b -> c) -> (a -> t b) -> a -> t c ; g ^. f = map g . f (.^) :: (Functor t) => (t b -> c) -> (a -> b) -> t a -> c ; g .^ f = g . map f (^.:) :: (Functor t) => (c -> d) -> (a -> b -> t c) -> a -> b -> t d ; g ^.: f = map g .: f (^..:) :: (Functor t) => (d -> e) -> (a -> b -> c -> t d) -> a -> b -> c -> t e ; g ^..: f = map g ..: f (^^.) :: (Functor t, Functor u) => (b -> c) -> (a -> t (u b)) -> a -> (t (u c)) ; g ^^. f = map (map g) . f class FunctorM (t :: * -> *) where mapM :: (Monad m) => (a -> m b) -> t a -> m (t b) mapOnM :: (FunctorM t, Monad m) => t a -> (a -> m b) -> m (t b) ; mapOnM = flip mapM sequence :: (FunctorM t, Monad m) => t (m a) -> m (t a) ; sequence = mapM id (^*@) :: (FunctorM t, Monad m) => (a -> m b) -> t a -> m (t b) ; (^*@) = mapM (^*$) :: (FunctorM t, Monad m) => (a -> m b) -> t a -> m (t b) ; (^*$) = mapM (^*.) :: (FunctorM t, Monad m) => (b -> m c) -> (a -> m b) -> t a -> m (t c) ; (g ^*. f) aT = mapM g *$ f ^*$ aT class (Unit t, Functor t) => Applicative (t :: * -> *) where (<@>) :: t (a -> b) -> t a -> t b pure :: (Applicative t) => a -> t a ; pure = unit (<$>) :: (Applicative t) => t (a -> b) -> t a -> t b ; (<$>) = (<@>) apair :: (Applicative t) => t a -> t b -> t (a, b) ; apair aA bA = pure (,) <@> aA <@> bA class Product (t :: * -> *) where (<*>) :: t a -> t b -> t (a, b) class (Product m) => Bind (m :: * -> *) where (>>=) :: m a -> (a -> m b) -> m b class (Applicative m, Bind m) => Monad (m :: * -> *) fail :: Chars -> m a ; fail = Prelude.error return :: (Monad m) => a -> m a ; return = pure kleisli :: (Monad m) => (a -> b) -> (a -> m b) ; kleisli = (.) return (>>) :: (Bind m) => m a -> m b -> m b ; aM >> bM = aM >>= const bM extend :: (Bind m) => (a -> m b) -> (m a -> m b) ; extend = flip (>>=) void :: (Functor m) => m a -> m () ; void = map (const ()) (*@) :: (Bind m) => (a -> m b) -> (m a -> m b) ; (*@) = extend (*$) :: (Bind m) => (a -> m b) -> (m a -> m b) ; (*$) = extend (*.) :: (Bind m) => (b -> m c) -> (a -> m b) -> (a -> m c) ; (g *. f) x = g *$ f x mjoin :: (Bind m) => m (m a) -> m a ; mjoin = extend id mmap :: (Monad m) => (a -> b) -> m a -> m b ; mmap f aM = return . f *$ aM mpair :: (Monad m) => m a -> m b -> m (a, b) mpair aM bM = do a <- aM b <- bM return (a, b) mapply :: (Monad m) => m (a -> b) -> m a -> m b mapply fM aM = do f <- fM a <- aM return $ f a when :: (Monad m) => Bool -> m () -> m () when True = id when False = const $ return () traverse :: (Iterable a t, Monad m) => (a -> m ()) -> t -> m () traverse f = foldl (\ m a -> m >> f a) $ return () traverseOn :: (Iterable a t, Monad m) => t -> (a -> m ()) -> m () ; traverseOn = flip traverse exec :: (Iterable (m ()) t, Monad m) => t -> m () ; exec = traverse id -- }}} -- Monad Transformers {{{ class Unit2 (t :: (* -> *) -> (* -> *)) where unit2 :: m ~> t m class Join2 (t :: (* -> *) -> (* -> *)) where join2 :: t (t m) ~> t m class Functor2 (t :: (* -> *) -> (* -> *)) where map2 :: (m ~> n) -> (t m ~> t n) class IsoFunctor2 (t :: (* -> *) -> (* -> *)) where isoMap2 :: (m ~> n, n ~> m) -> (t m ~> t n) class FunctorUnit2 (t :: (* -> *) -> (* -> *)) where funit2 :: (Functor m) => m ~> t m class FunctorJoin2 (t :: (* -> *) -> (* -> *)) where fjoin2 :: (Functor m) => t (t m) ~> t m class FunctorFunctor2 (t :: (* -> *) -> (* -> *)) where fmap2 :: (Functor m, Functor n) => (m ~> n) -> (t m ~> t n) class FunctorIsoFunctor2 (t :: (* -> *) -> (* -> *)) where fisoMap2 :: (Functor m, Functor n) => (m ~> n, n ~> m) -> (t m ~> t n) class MonadUnit2 (t :: (* -> *) -> (* -> *)) where munit2 :: (Monad m) => m ~> t m class MonadJoin2 (t :: (* -> *) -> (* -> *)) where mjoin2 :: (Monad m) => t (t m) ~> t m class MonadFunctor2 (t :: (* -> *) -> (* -> *)) where mmap2 :: (Monad m, Monad n) => (m ~> n) -> (t m ~> t n) class MonadIsoFunctor2 (t :: (* -> *) -> (* -> *)) where misoMap2 :: (Monad m, Monad n) => (m ~> n, n ~> m) -> (t m ~> t n) class MonadIO m where io :: IO ~> m class MonadQ m where liftQ :: Q ~> m -- }}} -- MonadMonoid {{{ class MonadBot (m :: * -> *) where mbot :: m a class MonadTop (m :: * -> *) where mtop :: m a class (MonadBot m) => MonadAppend (m :: * -> *) where (<++>) :: m a -> m a -> m a class (MonadBot m) => MonadPlus (m :: * -> *) where (<+>) :: m a -> m a -> m a guard :: (Monad m, MonadBot m) => Bool -> m () guard True = return () guard False = mbot maybeZero :: (Monad m, MonadBot m) => Maybe a -> m a maybeZero Nothing = mbot maybeZero (Just a) = return a mconcat :: (Iterable (m a) t, MonadAppend m) => t -> m a mconcat = foldr (<++>) mbot mlist :: (Iterable a t, Monad m, MonadAppend m) => t -> m a mlist = foldr ((<++>) . return) mbot msum :: (Iterable (m a) t, MonadPlus m) => t -> m a msum = iter (<+>) mbot mset :: (Iterable a t, Monad m, MonadPlus m) => t -> m a mset = iter ((<+>) . return) mbot many :: (Monad m, MonadAppend m) => m a -> m [a] many aM = mconcat [ oneOrMoreList aM , return [] ] oneOrMore :: (Monad m, MonadAppend m) => m a -> m (a, [a]) oneOrMore aM = do x <- aM xs <- many aM return (x, xs) twoOrMore :: (Monad m, MonadAppend m) => m a -> m (a, a, [a]) twoOrMore aM = do x1 <- aM (x2, xs) <- oneOrMore aM return (x1, x2, xs) oneOrMoreList :: (Monad m, MonadAppend m) => m a -> m [a] oneOrMoreList = uncurry (:) ^. oneOrMore -- }}} -- MonadMaybe {{{ newtype MaybeT m a = MaybeT { unMaybeT :: m (Maybe a) } class MonadMaybe (m :: * -> *) where maybeI :: m ~> MaybeT m maybeE :: MaybeT m ~> m obsMaybe :: (MonadMaybe m) => m a -> m (Maybe a) ; obsMaybe = unMaybeT . maybeI effMaybe :: (MonadMaybe m) => m (Maybe a) -> m a ; effMaybe = maybeE . MaybeT abort :: (Monad m, MonadMaybe m) => m a ; abort = effMaybe $ return Nothing mtry :: (Monad m, MonadMaybe m, Iterable (m a) t) => t -> m a ; mtry = foldr (<|>) abort (<|>) :: (Monad m, MonadMaybe m) => m a -> m a -> m a aM1 <|> aM2 = do aM' <- obsMaybe aM1 case aM' of Just a -> return a Nothing -> aM2 -- }}} -- MonadError {{{ newtype ErrorT e m a = ErrorT { unErrorT :: m (e :+: a) } class MonadError e (m :: * -> *) | m -> e where errorI :: m ~> ErrorT e m errorE :: ErrorT e m ~> m obsError :: (MonadError e m) => m a -> m (e :+: a) ; obsError = unErrorT . errorI effError :: (MonadError e m) => m (e :+: a) -> m a ; effError = errorE . ErrorT sumError :: (Monad m, MonadError e m) => e :+: a -> m a ; sumError = effError . return throw :: (Monad m, MonadError e m) => e -> m a ; throw e = sumError $ Inl e catch :: (Monad m, MonadError e m) => m a -> (e -> m a) -> m a catch aM h = do aeM <- unErrorT $ errorI aM case aeM of Inl e -> h e Inr a -> return a -- }}} -- MonadReader {{{ newtype ReaderT r m a = ReaderT { unReaderT :: r -> m a } class MonadReader r (m :: * -> *) | m -> r where readerI :: m ~> ReaderT r m readerE :: ReaderT r m ~> m runReaderT :: r -> ReaderT r m a -> m a ; runReaderT = flip unReaderT obsReader :: (MonadReader r m) => m a -> (r -> m a) ; obsReader = unReaderT . readerI effReader :: (MonadReader r m) => (r -> m a) -> m a ; effReader = readerE . ReaderT ask :: (Monad m, MonadReader r m) => m r ; ask = effReader return local :: (MonadReader r m) => (r -> r) -> m a -> m a ; local f aM = effReader $ obsReader aM . f localSet :: (MonadReader r m) => r -> m a -> m a ; localSet = local . const askL :: (Monad m, MonadReader r m) => Lens r a -> m a ; askL l = access l ^$ ask localL :: (MonadReader r m) => Lens r b -> (b -> b) -> m a -> m a ; localL = local .: update localSetL :: (MonadReader r m) => Lens r b -> b -> m a -> m a ; localSetL l = localL l . const -- }}} -- MonadWriter {{{ newtype WriterT o m a = WriterT { unWriterT :: m (o, a) } class MonadWriter o m | m -> o where writerI :: m ~> WriterT o m writerE :: WriterT o m ~> m obsWriter :: (MonadWriter o m) => m a -> m (o, a) ; obsWriter = unWriterT . writerI effWriter :: (MonadWriter o m) => m (o, a) -> m a ; effWriter = writerE . WriterT tell :: (Monad m, MonadWriter o m) => o -> m () ; tell = effWriter . return . (,()) hijack :: (MonadWriter o m) => m a -> m (o, a) ; hijack = obsWriter -- }}} -- MonadState {{{ newtype StateT s m a = StateT { unStateT :: s -> m (s, a) } class MonadState s m | m -> s where stateI :: m ~> StateT s m stateE :: StateT s m ~> m obsState :: (MonadState s m) => m a -> (s -> m (s, a)) ; obsState = unStateT . stateI effState :: (MonadState s m) => (s -> m (s, a)) -> m a ; effState = stateE . StateT get :: (Monad m, MonadState s m) => m s ; get = stateE $ StateT $ \ s -> return (s, s) put :: (Monad m, MonadState s m) => s -> m () ; put s = stateE $ StateT $ \ _ -> return (s, ()) modify :: (Monad m, MonadState s m) => (s -> s) -> m () ; modify = modifyM . kleisli modifyM :: (Monad m, MonadState s m) => (s -> m s) -> m () ; modifyM f = stateE $ StateT $ \ s -> f s <*> return () getL :: (Monad m, MonadState s m) => Lens s a -> m a ; getL l = map (access l) get putL :: (Monad m, MonadState s m) => Lens s a -> a -> m () ; putL = modify .: set modifyL :: (Monad m, MonadState s m) => Lens s a -> (a -> a) -> m () ; modifyL = modify .: update modifyLM :: (Monad m, MonadState s m) => Lens s a -> (a -> m a) -> m () ; modifyLM = modifyM .: updateM next :: (Monad m, MonadState s m, Peano s) => m s next = do i <- get put $ suc i return i nextL :: (Monad m, MonadState s m, Peano a) => Lens s a -> m a nextL l = do i <- getL l putL l $ suc i return i bumpL :: (Monad m, MonadState s m, Peano a) => Lens s a -> m () bumpL l = modifyL l suc -- }}} -- MonadRWST {{{ newtype RWST r o s m a = RWST { unRWST :: ReaderT r (WriterT o (StateT s m)) a } class (MonadReader r m, MonadWriter o m, MonadState s m) => MonadRWS r o s m where rwsI :: m ~> RWST r o s m rwsE :: RWST r o s m ~> m -- }}} -- MonadCont {{{ newtype ContT r m a = ContT { unContT :: (a -> m r) -> m r } class MonadCont r m | m -> r where contI :: m ~> ContT r m contE :: ContT r m ~> m obsCont :: (MonadCont r m) => m a -> ((a -> m r) -> m r) ; obsCont = unContT . contI effCont :: (MonadCont r m) => ((a -> m r) -> m r) -> m a ; effCont = contE . ContT callCC :: (MonadCont r m) => ((a -> m r) -> m r) -> m a ; callCC = effCont withC :: (MonadCont r m) => (a -> m r) -> m a -> m r ; withC = flip obsCont reset :: (Monad m, MonadCont r m) => m r -> m r ; reset aM = callCC $ \ k -> k *$ withC return aM modifyC :: (Monad m, MonadCont r m) => (r -> m r) -> m a -> m a ; modifyC f aM = callCC $ \ k -> withC (f *. k) aM -- }}} -- MonadOpaqueCont {{{ newtype OpaqueContT k r m a = OpaqueContT { unOpaqueContT :: k r m a -> m r } class MonadOpaqueCont k r m | m -> k, m -> r where opaqueContI :: m ~> OpaqueContT k r m opaqueContE :: OpaqueContT k r m ~> m obsOpaqueCont :: (MonadOpaqueCont k r m) => m a -> (k r m a -> m r) ; obsOpaqueCont = unOpaqueContT . opaqueContI effOpaqueCont :: (MonadOpaqueCont k r m) => (k r m a -> m r) -> m a ; effOpaqueCont = opaqueContE . OpaqueContT opaqueWithC :: (MonadOpaqueCont k r m) => k r m a -> m a -> m r ; opaqueWithC = flip obsOpaqueCont opaqueCallCC :: (MonadOpaqueCont k r m) => (k r m a -> m r) -> m a ; opaqueCallCC = effOpaqueCont -- }}} -- Observing and eliminating containers {{{ class Container e t | t -> e where (?) :: t -> e -> Bool elem :: (Container e t) => e -> t -> Bool elem = flip (?) class Indexed k v t | t -> k, t -> v where (#) :: t -> k -> Maybe v index :: (Indexed k v t) => t -> k -> Maybe v index = (#) (#!) :: (Indexed k v t) => t -> k -> v (#!) = unsafe_coerce justL .: (#) lookup :: (Indexed k v t) => k -> t -> Maybe v lookup = flip (#) class Iterable a t | t -> a where -- the left fold, exposing the fold continuation foldlk :: (b -> a -> (b -> b) -> b) -> b -> t -> b foldlk f i0 t = foldl (\ (iK :: (b -> b) -> b) (a :: a) (k :: b -> b) -> iK $ \ i -> f i a k) ($ i0) t id -- the left fold foldl :: (b -> a -> b) -> b -> t -> b foldl f = foldlk $ \ i a k -> let i' = f i a in i' `seq` k i' -- the right fold foldr :: (a -> b -> b) -> b -> t -> b foldr f = foldlk $ \ i a k -> f a $ k i -- the most efficient fold (unspecified order) iter :: (a -> b -> b) -> b -> t -> b iter = foldl . flip size :: (Integral n) => t -> n size = iter (const suc) 0 foldlOn :: (Iterable a t) => t -> b -> (b -> a -> b) -> b ; foldlOn = mirror foldl foldlFrom :: (Iterable a t) => b -> (b -> a -> b) -> t -> b ; foldlFrom = flip foldl foldrOn :: (Iterable a t) => t -> b -> (a -> b -> b) -> b ; foldrOn = mirror foldr foldrFrom :: (Iterable a t) => b -> (a -> b -> b) -> t -> b ; foldrFrom = flip foldr iterOn :: (Iterable a t) => t -> b -> (a -> b -> b) -> b ; iterOn = mirror iter iterFrom :: (Iterable a t) => b -> (a -> b -> b) -> t -> b ; iterFrom = flip iter isElem :: (Iterable a t, Eq a) => a -> t -> Bool isElem x = foldlk (\ _ x' k -> if x == x' then True else k False) False elemAtN :: (Iterable a t, Peano n, Eq n) => n -> t -> Maybe a elemAtN n t = case foldlk ff (Inr zer) t of Inl x -> Just x Inr _ -> Nothing where ff (Inr i) x' k = if i == n then Inl x' else k $ Inr $ suc i ff (Inl _) _ _ = error "internal error" toList :: (Iterable a t) => t -> [a] ; toList = foldr (:) [] toSet :: (Ord a, Iterable a t) => t -> Set a ; toSet = foldr insert empty toMap :: (Ord k, Iterable (k, v) t) => t -> Map k v ; toMap = foldr (uncurry mapInsert) mapEmpty toMapJoin :: (Ord k, Iterable (k, v) t, Join v) => t -> Map k v ; toMapJoin = foldr (uncurry $ mapInsertWith (\/)) mapEmpty -- }}} -- Creating containers {{{ class Buildable a t | t -> a where { nil :: t ; (&) :: a -> t -> t } build :: (Buildable a t) => [a] -> t ; build = foldr (&) nil single :: (Buildable a t) => a -> t ; single = flip (&) nil filter :: (Iterable a t, Buildable a t) => (a -> Bool) -> t -> t filter p = foldrFrom nil $ \ x -> if p x then (x &) else id reverse :: (Iterable a t, Buildable a t) => t -> t reverse = foldlFrom nil $ flip (&) uniques :: (Eq a, Iterable a t, Buildable a t) => t -> t uniques = foldrFrom nil $ \ x xs -> x & filter ((/=) x) xs replicate :: (Eq n, Peano n, Iterable a t, Buildable a t) => n -> a -> t replicate n = piterOn n nil . (&) fromList :: (Buildable a t) => [a] -> t ; fromList = foldr (&) nil fromSet :: (Buildable a t) => Set a -> t ; fromSet = foldr (&) nil fromMap :: (Buildable (k, v) t) => Map k v -> t ; fromMap = foldr (&) nil -- }}} ---------- -- Data -- ---------- -- Function {{{ applyTo :: a -> (a -> b) -> b ; applyTo = flip ($) (.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d) ; (.:) = (.) . (.) (..:) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e) ; (..:) = (.) . (.:) (...:) :: (e -> f) -> (a -> b -> c -> d -> e) -> (a -> b -> c -> d -> f) ; (...:) = (.) . (..:) (....:) :: (f -> g) -> (a -> b -> c -> d -> e -> f) -> (a -> b -> c -> d -> e -> g) ; (....:) = (.) . (...:) rotateR :: (a -> b -> c -> d) -> (c -> a -> b -> d) ; rotateR f c a b = f a b c rotateL :: (a -> b -> c -> d) -> (b -> c -> a -> d) ; rotateL f b c a = f a b c mirror :: (a -> b -> c -> d) -> (c -> b -> a -> d) ; mirror f c b a = f a b c on :: (b -> b -> c) -> (a -> b) -> (a -> a -> c) ; on p f x y = p (f x) (f y) composition :: [a -> a] -> a -> a ; composition = unEndo . concat . map Endo instance Category (->) where { catid = id ; (<.>) = (.) } instance Functor ((->) a) where map = (.) instance (Monoid b) => Monoid (a -> b) where { null = const null ; (++) f g x = f x ++ g x } instance (Bot b) => Bot (a -> b) where bot = const bot instance (Join b) => Join (a -> b) where (f \/ g) x = f x \/ g x instance (Top b) => Top (a -> b) where top = const top instance (Meet b) => Meet (a -> b) where (f /\ g) x = f x /\ g x instance (Neg b) => Neg (a -> b) where neg f = neg . f instance (JoinLattice b) => JoinLattice (a -> b) instance (MeetLattice b) => MeetLattice (a -> b) instance (Lattice b) => Lattice (a -> b) instance (NegLattice b) => NegLattice (a -> b) -- }}} -- Endo {{{ data Endo a = Endo { unEndo :: a -> a } runEndo :: a -> Endo a -> a ; runEndo = flip unEndo instance Monoid (Endo a) where { null = Endo id ; g ++ f = Endo $ unEndo g . unEndo f } data KleisliEndo m a = KleisliEndo { unKleisliEndo :: a -> m a } runKleisliEndo :: a -> KleisliEndo m a -> m a ; runKleisliEndo = flip unKleisliEndo instance (Monad m) => Monoid (KleisliEndo m a) where null = KleisliEndo return g ++ f = KleisliEndo $ unKleisliEndo g *. unKleisliEndo f -- }}} -- Bool {{{ ifThenElse :: Bool -> a -> a -> a ; ifThenElse c x y = case c of { True -> x ; False -> y } fif :: Bool -> a -> a -> a ; fif = ifThenElse cond :: (a -> Bool) -> c -> c -> (a -> c) ; cond p t f x = if p x then t else f instance Bot Bool where bot = False instance Join Bool where (\/) = (||) instance Top Bool where top = True instance Meet Bool where (/\) = (&&) instance Monoid Bool where { null = bot ; (++) = (\/) } instance ToString Bool where toString = show instance JoinLattice Bool instance MeetLattice Bool instance Lattice Bool -- }}} -- Integer {{{ instance ToInteger Integer where toInteger = id instance FromInteger Integer where fromInteger = id instance ToInt Integer where toInt = Prelude.fromIntegral instance FromInt Integer where fromInt = Prelude.fromIntegral instance ToRational Integer where toRational = Prelude.fromIntegral instance ToDouble Integer where toDouble = Prelude.fromIntegral instance ToString Integer where toString = show instance Peano Integer where { zer = 0 ; suc = Prelude.succ } instance Additive Integer where { zero = 0 ; (+) = (Prelude.+) } instance Subtractive Integer where (-) = (Prelude.-) instance Multiplicative Integer where { one = 1 ; (*) = (Prelude.*) } instance TruncateDivisible Integer where (//) = Prelude.div instance PartialOrder Integer where pcompare = fromOrdering .: compare instance Join Integer where (\/) = Prelude.max instance Meet Integer where (/\) = Prelude.min instance Neg Integer where neg = negate instance Monoid Integer where { null = 0 ; (++) = (+) } instance Integral Integer -- }}} -- Int {{{ instance ToInteger Int where toInteger = Prelude.toInteger instance FromInteger Int where fromInteger = Prelude.fromIntegral instance ToInt Int where toInt = id instance FromInt Int where fromInt = id instance ToRational Int where toRational = Prelude.fromIntegral instance ToDouble Int where toDouble = Prelude.fromIntegral instance ToString Int where toString = show instance Peano Int where { zer = 0 ; suc = Prelude.succ } instance Additive Int where { zero = 0 ; (+) = (Prelude.+) } instance Subtractive Int where (-) = (Prelude.-) instance Multiplicative Int where { one = 1 ; (*) = (Prelude.*) } instance TruncateDivisible Int where (//) = Prelude.div instance PartialOrder Int where pcompare = fromOrdering .: compare instance Bot Int where bot = Prelude.minBound instance Join Int where (\/) = Prelude.max instance Top Int where top = Prelude.maxBound instance Meet Int where (/\) = Prelude.min instance Neg Int where neg = negate instance Monoid Int where { null = 0 ; (++) = (+) } instance Integral Int instance JoinLattice Int instance MeetLattice Int instance Lattice Int instance NegLattice Int -- }}} -- Rational {{{ instance FromInteger Rational where fromInteger = Prelude.fromInteger instance FromInt Rational where fromInt = Prelude.fromIntegral instance ToRational Rational where toRational = id instance FromRational Rational where fromRational = id instance ToDouble Rational where toDouble = Prelude.fromRational instance FromDouble Rational where fromDouble = Prelude.toRational instance ToString Rational where toString = show instance Peano Rational where { zer = 0 ; suc = (1+) } instance Additive Rational where { zero = 0 ; (+) = (Prelude.+) } instance Subtractive Rational where (-) = (Prelude.-) instance Multiplicative Rational where { one = 1 ; (*) = (Prelude.*) } instance Divisible Rational where (/) = (Prelude./) instance PartialOrder Rational where pcompare = fromOrdering .: compare instance Join Rational where (\/) = Prelude.max instance Meet Rational where (/\) = Prelude.min instance Neg Rational where neg = negate instance Monoid Rational where { null = 0 ; (++) = (+) } instance Fractional Rational -- }}} -- Double {{{ instance FromInteger Double where fromInteger = Prelude.fromInteger instance FromInt Double where fromInt = Prelude.fromIntegral instance ToRational Double where toRational = Prelude.toRational instance FromRational Double where fromRational = Prelude.fromRational instance ToDouble Double where toDouble = id instance FromDouble Double where fromDouble = id instance ToString Double where toString = show instance Peano Double where { zer = 0 ; suc = (1+) } instance Additive Double where { zero = 0 ; (+) = (Prelude.+) } instance Subtractive Double where (-) = (Prelude.-) instance Multiplicative Double where { one = 1 ; (*) = (Prelude.*) } instance Divisible Double where (/) = (Prelude./) instance PartialOrder Double where pcompare = fromOrdering .: compare instance Join Double where (\/) = Prelude.max instance Meet Double where (/\) = Prelude.min instance Neg Double where neg = negate instance Monoid Double where { null = 0 ; (++) = (+) } instance Fractional Double -- }}} -- String {{{ type String = Text type Chars = [Char] fromChars :: Chars -> String ; fromChars = Text.pack fromString :: Chars -> String ; fromString = fromChars toChars :: String -> Chars ; toChars = Text.unpack error :: String -> a ; error = Prelude.error . toChars show :: (Prelude.Show a) => a -> String ; show = fromChars . Prelude.show read :: (Prelude.Read a) => String -> a ; read = Prelude.read . toChars instance ToString Char where toString = show instance Monoid String where { null = Text.empty ; (++) = Text.append } instance ToString String where toString = show instance Container Char String where s ? c = is justL $ Text.find (== c) s instance Iterable Char String where foldl = Text.foldl' foldr = Text.foldr iter = foldl . flip size = fromInt . Text.length -- }}} -- Lens {{{ data Cursor a b = Cursor { focus :: a, construct :: a -> b } data Lens a b = Lens { unLens :: a -> Cursor b a } lens :: (a -> b) -> (a -> b -> a) -> Lens a b ; lens getter setter = Lens $ \ s -> Cursor (getter s) (setter s) isoLens :: (a -> b) -> (b -> a) -> Lens a b ; isoLens to from = lens to $ const from update :: Lens a b -> (b -> b) -> a -> a ; update l f a = let Cursor b ba = unLens l a in ba $ f b updateM :: (Monad m) => Lens a b -> (b -> m b) -> a -> m a ; updateM l f a = let Cursor b ba = unLens l a in map ba $ f b access :: Lens a b -> a -> b ; access = focus .: unLens (~:) :: Lens a b -> (b -> b) -> a -> a ; (~:) = update set :: Lens a b -> b -> a -> a ; set l = update l . const (=:) :: Lens a b -> b -> a -> a ; (=:) = set (|:) :: a -> (a -> a) -> a ; (|:) = applyTo instance Category Lens where catid = isoLens id id g <.> f = Lens $ \ a -> let Cursor b ba = unLens f a Cursor c cb = unLens g b in Cursor c $ ba . cb -- }}} -- Prism {{{ data Prism a b = Prism { inject :: b -> a, view :: a -> Maybe b } prism :: (b -> a) -> (a -> Maybe b) -> Prism a b ; prism = Prism isoPrism :: (b -> a) -> (a -> b) -> Prism a b ; isoPrism from to = prism from $ Just . to unsafe_coerce :: Prism a b -> a -> b ; unsafe_coerce = maybeElim (error "unsafe_coerce") id .: view is :: Prism a b -> a -> Bool ; is = maybeElim False (const True) .: view alter :: Prism a b -> (b -> b) -> a -> a ; alter p f a = maybeElim a (inject p . f) $ view p a (~^) :: Prism a b -> (b -> b) -> a -> a ; (~^) = alter pset :: Prism a b -> b -> a -> a ; pset p = alter p . const (=^) :: Prism a b -> b -> a -> a ; (=^) = pset instance Category Prism where catid = isoPrism id id g <.> f = Prism { view = view g *. view f , inject = inject f . inject g } -- }}} -- Compose {{{ newtype (t :.: u) a = Compose { unCompose :: t (u a) } deriving (Eq, Ord, Bot, Join, JoinLattice, Top, Meet, MeetLattice, Lattice, PartialOrder) onComposeIso :: (t (u a) -> t (u b)) -> (t :.: u) a -> (t :.: u) b ; onComposeIso f (Compose x) = Compose $ f x instance (Functor t, Functor u) => Functor (t :.: u) where map = onComposeIso . map . map instance (Functorial JoinLattice t, Functorial JoinLattice u) => Functorial JoinLattice (t :.: u) where functorial :: forall a. (JoinLattice a) => W (JoinLattice ((t :.: u) a)) functorial = with (functorial :: W (JoinLattice (u a))) $ with (functorial :: W (JoinLattice (t (u a)))) $ W -- Tuple {{{ swap :: (a, b) -> (b, a) ; swap (x, y) = (y, x) fstL :: Lens (a, b) a ; fstL = lens fst $ \ (_,b) -> (,b) sndL :: Lens (a, b) b ; sndL = lens snd $ \ (a,_) -> (a,) mapFst :: (a -> a') -> (a, b) -> (a', b) ; mapFst f (a, b) = (f a, b) mapSnd :: (b -> b') -> (a, b) -> (a, b') ; mapSnd f (a, b) = (a, f b) instance (PartialOrder a, PartialOrder b) => PartialOrder (a, b) where (a1, b1) ⊑ (a2, b2) = (a1 ⊑ a2) /\ (b1 ⊑ b2) instance (PartialOrder a, PartialOrder b, PartialOrder c) => PartialOrder (a, b, c) where (a1, b1, c1) ⊑ (a2, b2, c2) = (a1 ⊑ a2) /\ (b1 ⊑ b2) /\ (c1 ⊑ c2) instance (PartialOrder a, PartialOrder b, PartialOrder c, PartialOrder d, PartialOrder e) => PartialOrder (a, b, c, d, e) where (a1, b1, c1, d1, e1) ⊑ (a2, b2, c2, d2, e2) = (a1 ⊑ a2) /\ (b1 ⊑ b2) /\ (c1 ⊑ c2) /\ (d1 ⊑ d2) /\ (e1 ⊑ e2) instance (Monoid a, Monoid b) => Monoid (a, b) where null = (null, null) (a1, b1) ++ (a2, b2) = (a1 ++ a2, b1 ++ b2) instance (Bot a, Bot b) => Bot (a, b) where bot = (bot, bot) instance (Join a, Join b) => Join (a, b) where (a1, b1) \/ (a2, b2) = (a1 \/ a2, b1 \/ b2) instance (JoinLattice a, JoinLattice b) => JoinLattice (a, b) instance (Bot a, Bot b, Bot c) => Bot (a, b, c) where bot = (bot, bot, bot) instance (Join a, Join b, Join c) => Join (a, b, c) where (a1, b1, c1) \/ (a2, b2, c2) = (a1 \/ a2, b1 \/ b2, c1 \/ c2) instance (JoinLattice a, JoinLattice b, JoinLattice c) => JoinLattice (a, b, c) instance (Bot a, Bot b, Bot c, Bot d, Bot e) => Bot (a, b, c, d, e) where bot = (bot, bot, bot, bot, bot) instance (Join a, Join b, Join c, Join d, Join e) => Join (a, b, c, d, e) where (a1, b1, c1, d1, e1) \/ (a2, b2, c2, d2, e2) = (a1 \/ a2, b1 \/ b2, c1 \/ c2, d1 \/ d2, e1 \/ e2) instance (JoinLattice a, JoinLattice b, JoinLattice c, JoinLattice d, JoinLattice e) => JoinLattice (a, b, c, d, e) instance (JoinLattice a) => Functorial JoinLattice ((,) a) where functorial = W instance (Difference a, Difference b) => (Difference (a, b)) where (a1, b1) \\ (a2, b2) = (a1 \\ a2, b1 \\ b2) instance Bifunctorial Eq (,) where bifunctorial = W instance Bifunctorial Ord (,) where bifunctorial = W -- }}} -- Sum {{{ data a :+: b = Inl a | Inr b deriving (Eq, Ord) sumElim :: (a -> c) -> (b -> c) -> a :+: b -> c ; sumElim f g = \case { Inl a -> f a ; Inr b -> g b } inlL :: Prism (a :+: b) a ; inlL = Prism Inl $ sumElim Just $ const Nothing inrL :: Prism (a :+: b) b ; inrL = Prism Inr $ sumElim (const Nothing) Just mapInl :: (a -> a') -> a :+: b -> a' :+: b ; mapInl f = sumElim (Inl . f) Inr mapInr :: (b -> b') -> a :+: b -> a :+: b' ; mapInr f = sumElim Inl $ Inr . f mapSum :: (a -> a') -> (b -> b') -> a :+: b -> a' :+: b' ; mapSum f g = sumElim (Inl . f) (Inr . g) instance MonadError a ((:+:) a) where errorI :: a :+: b -> ErrorT a ((:+:) a) b errorI ab = ErrorT $ Inr ab errorE :: ErrorT a ((:+:) a) b -> a :+: b errorE aME = case unErrorT aME of Inl a -> Inl a Inr (Inl a) -> Inl a Inr (Inr b) -> Inr b instance Unit ((:+:) a) where unit = Inr instance Functor ((:+:) a) where map = mmap instance Product ((:+:) a) where (<*>) = mpair instance Applicative ((:+:) a) where (<@>) = mapply instance Bind ((:+:) a) where abM >>= k = sumElim Inl k abM instance Monad ((:+:) a) -- }}} -- }}} -- Maybe {{{ maybeElim :: b -> (a -> b) -> Maybe a -> b ; maybeElim i f = \case { Nothing -> i ; Just a -> f a } nothingL :: Prism (Maybe a) () ; nothingL = prism (const Nothing) $ maybeElim (Just ()) $ const Nothing justL :: Prism (Maybe a) a ; justL = Prism Just id maybeElimOn :: Maybe a -> b -> (a -> b) -> b ; maybeElimOn = rotateR maybeElim maybeNot :: a -> Maybe a -> a ; maybeNot x = maybeElim x id instance MonadMaybe Maybe where maybeI :: Maybe ~> MaybeT Maybe maybeI = MaybeT . Just maybeE :: MaybeT Maybe ~> Maybe maybeE aM = case unMaybeT aM of Nothing -> Nothing Just aM' -> aM' instance Monoid (Maybe a) where null = Nothing Just x ++ _ = Just x Nothing ++ aM = aM instance Bind Maybe where aM >>= k = maybeElim Nothing k aM instance Unit Maybe where unit = Just instance Functor Maybe where map = mmap instance Applicative Maybe where (<@>) = mapply instance Product Maybe where (<*>) = mpair instance MonadBot Maybe where mbot = null instance MonadAppend Maybe where (<++>) = (++) instance Monad Maybe -- }}} -- List {{{ nilL :: Prism [a] () ; nilL = Prism (const []) $ \case { [] -> Just () ; _:_ -> Nothing } consL :: Prism [a] (a,[a]) ; consL = Prism (uncurry (:)) $ \case { [] -> Nothing ; x:xs' -> Just (x,xs') } singleL :: Prism [a] a ; singleL = Prism single $ \case { [a] -> Just a ; _ -> Nothing } length :: (Peano n) => [a] -> n ; length = foldl (const . suc) zer mapHead :: (a -> a) -> [a] -> [a] mapHead _ [] = [] mapHead f (x:xs) = f x:xs mapTail :: (a -> a) -> [a] -> [a] mapTail _ [] = [] mapTail f (x:xs) = x:map f xs head :: [a] -> Maybe a head [] = Nothing head (x:_) = Just x tail :: [a] -> Maybe [a] tail [] = Nothing tail (_:xs) = Just xs zip :: [a] -> [b] -> Maybe [(a, b)] zip [] [] = return [] zip (_:_) [] = Nothing zip [] (_:_) = Nothing zip (x:xs) (y:ys) = do xys <- zip xs ys return $ (x,y) : xys unzip :: [(a, b)] -> ([a], [b]) unzip [] = ([], []) unzip ((x, y):xys) = let (xs, ys) = unzip xys in (x:xs, y:ys) firstN :: (Eq n, Integral n) => n -> [a] -> [a] firstN n = recur 0 where recur _ [] = [] recur i (x:xs) | i == n = [] | otherwise = x : recur (suc i) xs intersperse :: a -> [a] -> [a] intersperse _ [] = [] intersperse _ [x] = [x] intersperse i (x:xs) = x : recur xs where recur [] = [] recur (x':xs') = i : x' : recur xs' pluck :: [a] -> [[a]] -> Maybe ([a], [[a]]) pluck [] _ = Nothing pluck (x:xs) [] = Just ([x], [xs]) pluck (x1:xs1) (xs2:xss) = do (ys2, xss') <- pluck xs2 xss return (x1 : ys2, xs1 : xss') transpose :: [[a]] -> [[a]] transpose [] = [[]] transpose (xs:xss) = case pluck xs xss of Nothing -> [] Just (ys, xss') -> ys : transpose xss' bigProduct :: [[a]] -> [[a]] bigProduct [] = [[]] bigProduct (xs:xss) = do let xss' = bigProduct xss x <- xs map (x:) xss' instance Iterable a [a] where foldl _ i [] = i foldl f i (x:xs) = let i' = f i x in i' `seq` foldl f i' xs foldlk _ i [] = i foldlk f i (x:xs) = f i x $ \ i' -> i' `seq` foldlk f i' xs foldr _ i [] = i foldr f i (x:xs) = f x $ foldr f i xs instance (Eq k) => Indexed k v [(k, v)] where [] # _ = Nothing ((k,v):kvs) # k' | k == k' = Just v | otherwise = kvs # k' instance Bind [] where [] >>= _ = [] (x:xs) >>= k = k x ++ (xs >>= k) instance FunctorM [] where mapM _ [] = return [] mapM f (x:xs) = do y <- f x ys <- mapM f xs return $ y:ys instance (Eq a) => Container a [a] where (?) = flip isElem instance Buildable a [a] where { nil = [] ; (&) = (:) } instance Monoid [a] where { null = [] ; xs ++ ys = foldr (:) ys xs } instance Unit [] where unit = (:[]) instance Functor [] where map f = foldr ((:) . f) [] instance Product [] where (<*>) = mpair instance Applicative [] where (<@>) = mapply instance MonadBot [] where mbot = [] instance MonadAppend [] where (<++>) = (++) instance Functorial Monoid [] where functorial = W instance Functorial Eq [] where functorial = W instance Functorial Ord [] where functorial = W instance Monad [] -- }}} -- Set {{{ data Set a where EmptySet :: Set a Set :: (Ord a) => Set.Set a -> Set a setPrimElim :: b -> ((Ord a) => Set.Set a -> b) -> Set a -> b setPrimElim i f = \case { EmptySet -> i ; Set x -> f x } setPrimElimOn :: Set a -> b -> ((Ord a) => Set.Set a -> b) -> b setPrimElimOn = rotateR setPrimElim setPrimElim2 :: b -> ((Ord a) => Set.Set a -> b) -> ((Ord a) => Set.Set a -> b) -> ((Ord a) => Set.Set a -> Set.Set a -> b) -> Set a -> Set a -> b setPrimElim2 i f1 f2 ff s1 s2 = setPrimElimOn s1 (setPrimElimOn s2 i f1) $ \ p1 -> setPrimElimOn s2 (f2 p1) $ \ p2 -> ff p1 p2 setPrimElim2' :: b -> ((Ord a) => Set.Set a -> b) -> ((Ord a) => Set.Set a -> Set.Set a -> b) -> Set a -> Set a -> b setPrimElim2' i f = setPrimElim2 i f f toPrimSet :: Set a -> Set.Set a toPrimSet = setPrimElim Set.empty id learnSet :: Set a -> b -> ((Ord a) => b) -> b learnSet s i f = setPrimElimOn s i $ const f empty :: Set a ; empty = EmptySet isEmpty :: Set a -> Bool ; isEmpty = setPrimElim True Set.null insert :: (Ord a) => a -> Set a -> Set a insert e = setPrimElim (Set $ Set.singleton e) $ Set . Set.insert e union :: Set a -> Set a -> Set a union = setPrimElim2' EmptySet Set $ Set .: Set.union intersection :: Set a -> Set a -> Set a intersection = setPrimElim2' EmptySet (const EmptySet) $ Set .: Set.intersection remove :: Set a -> Maybe (a, Set a) remove = setPrimElim Nothing $ map (mapSnd Set) . Set.minView setDiff :: Set a -> Set a -> Set a setDiff = setPrimElim2 EmptySet (const EmptySet) Set $ Set .: (Set.\\) setMap :: (Ord b) => (a -> b) -> Set a -> Set b setMap f = setPrimElim EmptySet $ Set . Set.map f setMapOn :: (Ord b) => Set a -> (a -> b) -> Set b setMapOn = flip setMap maybeSet :: (Ord a) => Maybe a -> Set a maybeSet = maybeElim empty single setTranspose :: Set (Set a) -> Set (Set a) setTranspose aMM = loop $ toList aMM where loop :: [(Set a)] -> Set (Set a) loop [] = EmptySet loop (s:ss) = learnSet s (loop ss) $ toSet $ map toSet $ transpose $ map toList $ s:ss setBigProduct :: Set (Set a) -> Set (Set a) setBigProduct s = case remove s of Nothing -> single empty Just (xs, xss) -> learnSet xs empty $ do let xss' = setBigProduct xss x <- xs setMap (insert x) xss' instance Container a (Set a) where s ? e = setPrimElim False (Set.member e) s instance Iterable a (Set a) where { foldl f i = setPrimElim i $ Set.foldl' f i ; foldr f i = setPrimElim i $ Set.foldr' f i } instance (Ord a) => Buildable a (Set a) where { nil = empty ; (&) = insert } instance Eq (Set a) where (==) = setPrimElim2' True (Set.null) (==) instance Ord (Set a) where compare = setPrimElim2 EQ (\ s -> compare Set.empty s) (\ s -> compare s Set.empty) compare instance PartialOrder (Set a) where (⊑) = setPrimElim2 True (const True) (const False) $ Set.isSubsetOf instance Product Set where xs <*> ys = learnSet xs empty $ learnSet ys empty $ build $ toList xs <*> toList ys instance Bind Set where aM >>= k = joins $ map k $ toList aM instance MonadBot Set where mbot = empty instance MonadPlus Set where (<+>) = union instance MonadAppend Set where (<++>) = union instance Bot (Set a) where bot = empty instance Join (Set a) where (\/) = union instance Meet (Set a) where (/\) = intersection instance Monoid (Set a) where { null = empty ; (++) = union } instance Difference (Set a) where (\\) = setDiff instance JoinLattice (Set a) -- }}} -- Map {{{ data Map k v where EmptyMap :: Map k v Map :: (Ord k) => Map.Map k v -> Map k v type Old v = v type New v = v mapPrimElim :: b -> ((Ord k) => Map.Map k v -> b) -> Map k v -> b mapPrimElim i f = \case { EmptyMap -> i ; Map p -> f p } mapPrimElimOn :: Map k v -> b -> ((Ord k) => Map.Map k v -> b) -> b mapPrimElimOn = rotateR mapPrimElim mapPrimElim2 :: b -> ((Ord k) => Map.Map k v -> b) -> ((Ord k) => Map.Map k v -> b) -> ((Ord k) => Map.Map k v -> Map.Map k v -> b) -> Map k v -> Map k v -> b mapPrimElim2 i f1 f2 ff s1 s2 = mapPrimElimOn s1 (mapPrimElimOn s2 i f1) $ \ p1 -> mapPrimElimOn s2 (f2 p1) $ \ p2 -> ff p1 p2 mapPrimElim2' :: b -> ((Ord k) => Map.Map k v -> b) -> ((Ord k) => Map.Map k v -> Map.Map k v -> b) -> Map k v -> Map k v -> b mapPrimElim2' i f = mapPrimElim2 i f f toPrimMap :: Map k v -> Map.Map k v ; toPrimMap = mapPrimElim Map.empty id learnMap :: Map k v -> b -> ((Ord k) => b) -> b ; learnMap m i f = mapPrimElimOn m i $ const f mapEmpty :: Map k v ; mapEmpty = EmptyMap mapIsEmpty :: Map k v -> Bool ; mapIsEmpty = mapPrimElim True Map.null mapKeys :: Map k v -> Set k ; mapKeys = mapPrimElim empty $ Set . Map.keysSet mapInsert :: (Ord k) => k -> v -> Map k v -> Map k v ; mapInsert = mapInsertWith $ const id mapSingleton :: (Ord k) => k -> v -> Map k v ; mapSingleton k v = mapInsert k v mapEmpty mapInsertWith :: (Ord k) => (Old v -> New v -> v) -> k -> v -> Map k v -> Map k v mapInsertWith f k v = mapPrimElim (Map $ Map.singleton k v) $ Map . Map.insertWith (flip f) k v mapRemove :: Map k v -> Maybe ((k, v), Map k v) mapRemove = mapPrimElim Nothing $ map (mapSnd Map) . Map.minViewWithKey mapUnionWith :: (Old v -> New v -> v) -> Map k v -> Map k v -> Map k v mapUnionWith f = mapPrimElim2' mapEmpty Map $ Map .: Map.unionWith (flip f) mapIntersectionWith :: (Old v -> New v -> v) -> Map k v -> Map k v -> Map k v mapIntersectionWith f = mapPrimElim2' mapEmpty (const mapEmpty) $ Map .: Map.intersectionWith (flip f) mapModify :: (v -> v) -> k -> Map k v -> Map k v mapModify f k m = learnMap m mapEmpty $ case m # k of Nothing -> m Just x -> mapInsert k (f x) m onlyKeys :: (Ord k) => Set k -> Map k v -> Map k v onlyKeys s m = iterOn s mapEmpty $ \ k -> maybeElim id (mapInsert k) $ m # k mapFilter :: (v -> Bool) -> Map k v -> Map k v mapFilter f = mapPrimElim EmptyMap $ Map . Map.filter f mapNoBot :: (Bot v, Eq v) => Map k v -> Map k v mapNoBot = mapFilter (/= bot) instance Iterable (k, v) (Map k v) where foldl f i = mapPrimElim i $ Map.foldlWithKey' (curry . f) i foldr f i = mapPrimElim i $ Map.foldrWithKey' (curry f) i instance (Eq k, Eq v) => Eq (Map k v) where (==) = mapPrimElim2' True (Map.null) (==) instance (Ord k, Ord v) => Ord (Map k v) where compare = mapPrimElim2 EQ (\ m -> compare Map.empty m) (\ m -> compare m Map.empty) compare instance (Ord k, PartialOrder v) => PartialOrder (Map k v) where (⊑) = mapPrimElim2 True (const True) (const False) $ Map.isSubmapOfBy (⊑) instance Indexed k v (Map k v) where m # k = mapPrimElim Nothing (Map.lookup k) m instance (Eq v) => Container (k, v) (Map k v) where m ? (k,v) = maybeElim False (== v) $ m # k instance (Ord k) => Buildable (k, v) (Map k v) where { nil = mapEmpty ; (&) = uncurry mapInsert } instance Bot (Map k v) where bot = mapEmpty instance (Join v) => Join (Map k v) where (\/) = mapUnionWith (\/) instance (Monoid v) => Monoid (Map k v) where { null = mapEmpty ; (++) = mapUnionWith (++) } instance (Difference v) => Difference (Map k v) where (\\) = mapPrimElim2 EmptyMap (const EmptyMap) Map $ Map .: Map.differenceWith (Just .: (\\)) instance (JoinLattice v) => JoinLattice (Map k v) instance Functor (Map k) where map f = mapPrimElim EmptyMap $ Map . Map.map f -- }}} -- ListSet {{{ newtype ListSet a = ListSet { unListSet :: [a] } deriving (Container a, Iterable a, Buildable a , Monoid , Unit, Functor, Applicative, Product, Bind, Monad) instance FunctorM ListSet where mapM f = map ListSet . mapM f . unListSet listSetTranspose :: forall a. ListSet (ListSet a) -> ListSet (ListSet a) listSetTranspose = coerce (transpose :: [[a]] -> [[a]]) instance (Ord a) => PartialOrder (ListSet a) where pcompare = pcompare `on` toSet instance Bot (ListSet a) where bot = null instance Join (ListSet a) where (\/) = (++) instance MonadBot ListSet where mbot = bot instance MonadPlus ListSet where (<+>) = (\/) instance JoinLattice (ListSet a) -- }}} -- IO {{{ print :: (MonadIO m) => String -> m () ; print = io . Prelude.putStrLn . toChars failIO :: (MonadIO m) => String -> m a ; failIO = io . Prelude.fail . toChars instance Unit IO where unit = Prelude.return instance Functor IO where map = mmap instance Applicative IO where (<@>) = mapply instance Product IO where (<*>) = mpair instance Bind IO where (>>=) = (Prelude.>>=) instance MonadIO IO where io = id instance Monad IO -- }}} -- Q {{{ instance Unit Q where unit = Prelude.return instance Functor Q where map = mmap instance Applicative Q where (<@>) = mapply instance Product Q where (<*>) = mpair instance Bind Q where (>>=) = (Prelude.>>=) instance MonadQ Q where liftQ = id instance MonadBot Q where mbot = Prelude.fail $ toChars "mbot" instance Monad Q -- }}} -- Fix {{{ data Stamped a f = Stamped { stampedID :: a , stamped :: f } instance (Eq a) => Eq (Stamped a f) where (==) = (==) `on` stampedID instance (Ord a) => Ord (Stamped a f) where compare = compare `on` stampedID newtype Fix f = Fix { unFix :: f (Fix f) } instance (Functorial Eq f) => Eq (Fix f) where Fix x == Fix y = with (functorial :: W (Eq (f (Fix f)))) $ x == y instance (Functorial Eq f, Functorial Ord f) => Ord (Fix f) where Fix x `compare` Fix y = with (functorial :: W (Ord (f (Fix f)))) $ x `compare` y data StampedFix a f = StampedFix { stampedFixID :: a , stampedFix :: f (StampedFix a f) } stripStampedFix :: (Functor f) => StampedFix a f -> Fix f stripStampedFix (StampedFix _ f) = Fix $ map stripStampedFix f instance (Eq a) => Eq (StampedFix a f) where (==) = (==) `on` stampedFixID instance (Ord a) => Ord (StampedFix a f) where compare = compare `on` stampedFixID instance (PartialOrder a) => PartialOrder (StampedFix a f) where pcompare = pcompare `on` stampedFixID -- }}} -- Annotated {{{ data Annotated ann a = Annotated { annotation :: ann , annValue :: a } -- }}} -- ListSetWithTop {{{ data ListSetWithTop a = ListSetTop | ListSetNotTop (ListSet a) listSetWithTopElim :: b -> (ListSet a -> b) -> ListSetWithTop a -> b listSetWithTopElim i f = \case { ListSetTop -> i ; ListSetNotTop xs -> f xs } listSetWithTopTranspose :: ListSetWithTop (ListSetWithTop a) -> ListSetWithTop (ListSetWithTop a) listSetWithTopTranspose = listSetWithTopElim ListSetTop $ maybeElim ListSetTop (ListSetNotTop . map ListSetNotTop . listSetTranspose) . sequence . map (listSetWithTopElim Nothing Just) instance (Ord a) => PartialOrder (ListSetWithTop a) where ListSetTop `pcompare` ListSetTop = PEQ ListSetTop `pcompare` _ = PGT _ `pcompare` ListSetTop = PLT ListSetNotTop xs `pcompare` ListSetNotTop ys = xs `pcompare` ys instance Buildable a (ListSetWithTop a) where nil = ListSetNotTop nil _ & ListSetTop = ListSetTop x & ListSetNotTop xs = ListSetNotTop $ x & xs instance Bot (ListSetWithTop a) where bot = ListSetNotTop nil instance Join (ListSetWithTop a) where ListSetTop \/ _ = ListSetTop _ \/ ListSetTop = ListSetTop ListSetNotTop x \/ ListSetNotTop y = ListSetNotTop $ x ++ y instance Top (ListSetWithTop a) where top = ListSetTop instance Meet (ListSetWithTop a) where ListSetTop /\ x = x x /\ ListSetTop = x ListSetNotTop x /\ ListSetNotTop y = ListSetNotTop $ x ++ y instance (Ord a) => Difference (ListSetWithTop a) where ListSetTop \\ ListSetTop = nil ListSetTop \\ ListSetNotTop _ = ListSetTop ListSetNotTop _ \\ ListSetTop = nil ListSetNotTop xs \\ ListSetNotTop ys = fromSet $ toSet xs \\ toSet ys instance Monoid (ListSetWithTop a) where { null = bot ; (++) = (\/) } instance JoinLattice (ListSetWithTop a) instance MeetLattice (ListSetWithTop a) instance MonadBot ListSetWithTop where mbot = bot instance MonadPlus ListSetWithTop where (<+>) = (\/) instance MonadTop ListSetWithTop where mtop = top instance MonadAppend ListSetWithTop where (<++>) = (\/) instance Unit ListSetWithTop where unit = ListSetNotTop . single instance Bind ListSetWithTop where ListSetTop >>= _ = ListSetTop ListSetNotTop xs >>= f = joins $ map f xs instance Functor ListSetWithTop where map = mmap instance Product ListSetWithTop where (<*>) = mpair instance Applicative ListSetWithTop where (<@>) = mapply instance Monad ListSetWithTop -- }}} -- SetWithTop {{{ data SetWithTop a = SetTop | SetNotTop (Set a) deriving (Eq, Ord) setWithTopElim :: b -> (Set a -> b) -> SetWithTop a -> b setWithTopElim b _ SetTop = b setWithTopElim _ f (SetNotTop x) = f x setFromListWithTop :: (Ord a) => ListSetWithTop a -> SetWithTop a setFromListWithTop ListSetTop = SetTop setFromListWithTop (ListSetNotTop xs) = SetNotTop $ fromList $ toList xs listFromSetWithTop :: SetWithTop a -> ListSetWithTop a listFromSetWithTop SetTop = ListSetTop listFromSetWithTop (SetNotTop xs) = ListSetNotTop $ fromSet xs instance (Ord a) => PartialOrder (SetWithTop a) where SetTop `pcompare` SetTop = PEQ SetTop `pcompare` _ = PGT _ `pcompare` SetTop = PLT SetNotTop xs `pcompare` SetNotTop ys = xs `pcompare` ys instance Bot (SetWithTop a) where bot = SetNotTop empty instance (Ord a) => Buildable a (SetWithTop a) where nil = bot _ & SetTop = SetTop x & SetNotTop xs = SetNotTop $ x & xs instance Difference (SetWithTop a) where SetTop \\ SetTop = bot SetTop \\ SetNotTop _ = SetTop SetNotTop _ \\ SetTop = bot SetNotTop xs \\ SetNotTop ys = SetNotTop $ xs \\ ys instance Join (SetWithTop a) where SetTop \/ _ = SetTop _ \/ SetTop = SetTop SetNotTop x \/ SetNotTop y = SetNotTop $ x \/ y instance Top (SetWithTop a) where top = SetTop instance Meet (SetWithTop a) where SetTop /\ x = x x /\ SetTop = x SetNotTop x /\ SetNotTop y = SetNotTop $ x /\ y instance MonadBot SetWithTop where mbot = bot instance MonadPlus SetWithTop where (<+>) = (\/) instance MonadTop SetWithTop where mtop = top instance Product SetWithTop where SetTop <*> _ = SetTop _ <*> SetTop = SetTop SetNotTop xs <*> SetNotTop ys = SetNotTop $ xs <*> ys instance Bind SetWithTop where SetTop >>= _ = SetTop SetNotTop xs >>= f = joins $ setMap f xs instance JoinLattice (SetWithTop a) instance MeetLattice (SetWithTop a) -- }}} -- Constructive Classical {{{ data ConstructiveClassical a = Constructive (Set a) | Classical (a -> Bool) conClaPartition :: [ConstructiveClassical a] -> ([Set a], [a -> Bool]) conClaPartition = iter ff ([], []) where ff (Constructive c) (cs, ps) = (c : cs, ps) ff (Classical p) (cs, ps) = (cs, p : ps) conClaBigProduct :: (Ord a) => [ConstructiveClassical a] -> ListSetWithTop a conClaBigProduct xs = do let (cs, ps) = conClaPartition xs c = meets $ map SetNotTop cs p = joins ps case c of SetTop -> if is nilL ps then mbot else mtop SetNotTop candidates -> do candidate <- mlist $ toList candidates guard $ p candidate return candidate -- }}} -- SumOfProd {{{ newtype SumOfProd a = SumOfProd { unSumOfProd :: Set (Set a) } deriving (Eq, Ord) instance (Ord a) => Buildable a (SumOfProd a) where { nil = SumOfProd empty ; a & s = SumOfProd $ single (single a) \/ unSumOfProd s } sumOfProdMap :: (Ord b) => (a -> b) -> SumOfProd a -> SumOfProd b sumOfProdMap f = SumOfProd . setMap (setMap f) . unSumOfProd sumOfProdConcretize :: (Ord b) => (a -> ConstructiveClassical b) -> SumOfProd a -> SetWithTop b sumOfProdConcretize p v = setFromListWithTop $ conClaBigProduct *$ mlist $ map (map p . toList) $ toList $ unSumOfProd v instance Bot (SumOfProd a) where bot = SumOfProd empty instance Join (SumOfProd a) where sps1 \/ sps2 = SumOfProd $ unSumOfProd sps1 \/ unSumOfProd sps2 instance Meet (SumOfProd a) where sps₁ /\ sps₂ = SumOfProd $ do ps₁ <- unSumOfProd sps₁ ps₂ <- unSumOfProd sps₂ single $ ps₁ \/ ps₂ instance (Ord a, Neg a) => Neg (SumOfProd a) where neg = sumOfProdMap neg . SumOfProd . setBigProduct . unSumOfProd instance JoinLattice (SumOfProd a) -- }}}