{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Expression where
import Control.Applicative (Alternative, (<|>))
import Control.Monad ((<=<), (>=>))
import Data.Monoid (Alt (..))
import Data.Typeable (Typeable)
import Control.Monad.Trans.Reader (ReaderT (..))
import Control.Monad.Trans.Except (ExceptT (..))
import qualified Control.Monad.Trans.State.Lazy as L
import qualified Control.Monad.Trans.State.Strict as S
import qualified Control.Monad.Trans.Writer.Lazy as L
import qualified Control.Monad.Trans.Writer.Strict as S
import Data.Functor.Compose (Compose (..))
import Data.Functor.Const (Const (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Product (Product (..))
import Data.Functor.Reverse (Reverse (..))
import Data.Functor.Sum (Sum (..))
infixr 1 ^>>=
class HFunctor (h :: (u -> *) -> u -> *) where
hmap :: (forall b. t b -> t' b) -> h t a -> h t' a
default hmap :: (HTraversable h) => (forall b. t b -> t' b) -> h t a -> h t' a
hmap f = runIdentity . htraverse (Identity . f)
class HPointed h where
hpure :: t a -> h t a
class HBind h where
(^>>=) :: h t a -> (forall b. t b -> h t' b) -> h t' a
class (HFunctor h, HPointed h, HBind h) => HMonad h
hliftM :: (HPointed h, HBind h) => (forall b. t b -> t' b) -> h t a -> h t' a
hliftM f x = x ^>>= hpure . f
hjoin :: (HBind h) => h (h t) a -> h t a
hjoin x = x ^>>= id
class (HFunctor h) => HTraversable h where
{-# MINIMAL htraverse | hsequence #-}
htraverse
:: (Applicative f)
=> (forall b. t b -> f (t' b)) -> h t a -> f (h t' a)
htraverse f = hsequence . hmap (Compose . f)
hsequence
:: (Applicative f)
=> h (Compose f t) a -> f (h t a)
hsequence = htraverse getCompose
hfoldMapMonoid
:: (HTraversable h, Monoid m)
=> (forall b. t b -> m) -> h t a -> m
hfoldMapMonoid f = getConst . htraverse (Const . f)
hbindTraverse
:: (HTraversable h, HMonad h, Applicative f)
=> (forall b. t b -> f (h t' b))
-> h t a
-> f (h t' a)
hbindTraverse f = fmap hjoin . htraverse f
class HBifunctor (h :: (k -> *) -> (k -> *) -> k -> *) where
hbimap :: (forall b. s b -> s' b)
-> (forall b. t b -> t' b)
-> h s t a
-> h s' t' a
hfirst :: (forall b. s b -> s' b) -> h s t a -> h s' t a
hsecond :: (forall b. t b -> t' b) -> h s t a -> h s t' a
default hbimap
:: (HBitraversable h)
=> (forall b. s b -> s' b)
-> (forall b. t b -> t' b)
-> h s t a
-> h s' t' a
hbimap f g = runIdentity . hbitraverse (Identity . f) (Identity . g)
hfirst f = hbimap f id
hsecond = hbimap id
class (HBifunctor h) => HBitraversable h where
hbitraverse
:: (Applicative f)
=> (forall b. s b -> f (s' b))
-> (forall b. t b -> f (t' b))
-> h s t a -> f (h s' t' a)
hbifoldMapMonoid
:: (Monoid m, HBitraversable h)
=> (forall b. s b -> m) -> (forall b. t b -> m) -> h s t a -> m
hbifoldMapMonoid f g = getConst . hbitraverse (Const . f) (Const . g)
class HDuofunctor (h :: ((u -> *) -> u -> *) -> (u -> *) -> u -> *) where
hduomap
:: (forall g g' b. (forall c. g c -> g' c) -> s g b -> s' g' b)
-> (forall b. t b -> t' b)
-> h s t a
-> h s' t' a
default hduomap
:: (HDuotraversable h)
=> (forall g g' b. (forall c. g c -> g' c) -> s g b -> s' g' b)
-> (forall b. t b -> t' b)
-> h s t a
-> h s' t' a
hduomap f g =
runIdentity .
hduotraverse (\h -> Identity . f (runIdentity . h)) (Identity . g)
hduomapFirst
:: HDuofunctor h
=> (forall g g' b. (forall c. g c -> g' c) -> s g b -> s' g' b)
-> h s t a
-> h s' t a
hduomapFirst f = hduomap f id
hduomapFirst'
:: (HDuofunctor h, HFunctor s)
=> (forall g b. s g b -> s' g b) -> h s t a -> h s' t a
hduomapFirst' f = hduomapFirst (\g -> f . hmap g)
hduomapSecond
:: (HDuofunctor h, HFunctor s)
=> (forall b. t b -> t' b) -> h s t a -> h s t' a
hduomapSecond = hduomap hmap
class HDuofunctor h => HDuotraversable h where
hduotraverse
:: (Applicative f)
=> (forall g g' b. (forall c. g c -> f (g' c)) -> s g b -> f (s' g' b))
-> (forall b. t b -> f (t' b))
-> h s t a
-> f (h s' t' a)
hduotraverseFirst
:: (HDuotraversable h, Applicative f)
=> (forall g g' b. (forall c. g c -> f (g' c)) -> s g b -> f (s' g' b))
-> h s t a
-> f (h s' t a)
hduotraverseFirst f = hduotraverse f pure
hduotraverseFirst'
:: (HDuotraversable h, HTraversable s, Monad f)
=> (forall g b. s g b -> f (s' g b)) -> h s t a -> f (h s' t a)
hduotraverseFirst' f = hduotraverseFirst (\g -> f <=< htraverse g)
hduotraverseSecond
:: (HDuotraversable h, HTraversable s, Applicative f)
=> (forall b. t b -> f (t' b)) -> h s t a -> f (h s t' a)
hduotraverseSecond = hduotraverse htraverse
class HFoldableAt k h where
hfoldMap :: (forall b. t b -> k b) -> h t a -> k a
implHfoldMap
:: (HFunctor h)
=> (h k a -> k a)
-> (forall b. t b -> k b) -> h t a -> k a
implHfoldMap g f = g . hmap f
implHfoldMapCompose
:: (HTraversable h, Monad m)
=> (h k a -> m (k a))
-> (forall b. t b -> Compose m k b) -> h t a -> Compose m k a
implHfoldMapCompose f = implHfoldMap (Compose . (htraverse getCompose >=> f))
hfold :: HFoldableAt t h => h t a -> t a
hfold = hfoldMap id
hfoldA :: (HFoldableAt (Compose f t) h, Applicative f) => h t a -> f (t a)
hfoldA = hfoldMapA pure
hfoldMapA :: (HFoldableAt (Compose f k) h, Applicative f) => (forall b. t b -> f (k b)) -> h t a -> f (k a)
hfoldMapA f = getCompose . hfoldMap (Compose . f)
hfoldTraverse
:: (HFoldableAt k h, HTraversable h, Applicative f)
=> (forall b. t b -> f (k b))
-> h t a
-> f (k a)
hfoldTraverse f = fmap hfold . htraverse f
class HBifoldableAt k h where
hbifoldMap :: (forall b. f b -> k b) -> (forall b. g b -> k b) -> h f g a -> k a
hbifold :: (HBifoldableAt k h) => h k k a -> k a
hbifold = hbifoldMap id id
class HDuofoldableAt k h where
hduofoldMap
:: (HTraversable s)
=> (forall g b. (forall c. g c -> k c) -> s g b -> k b)
-> (forall b. t b -> k b)
-> h s t a
-> k a
implHduofoldMap
:: (HDuofunctor h, HFunctor s)
=> ((forall g b. (forall c. g c -> k c) -> s g b -> k b) -> h s k a -> k a)
-> (forall g b. (forall c. g c -> k c) -> s g b -> k b)
-> (forall b. t b -> k b)
-> h s t a
-> k a
implHduofoldMap h f g = h f . hduomap hmap g
implHduofoldMapCompose
:: (HDuotraversable h, HTraversable s, Monad m)
=> ((forall g b. (forall c. g c -> m (k c)) -> s g b -> m (k b)) -> h s k a -> m (k a))
-> (forall g b. (forall c. g c -> Compose m k c) -> s g b -> Compose m k b)
-> (forall b. t b -> Compose m k b)
-> h s t a
-> Compose m k a
implHduofoldMapCompose f =
implHduofoldMap
(\g ->
Compose .
(hduotraverseSecond getCompose >=>
f (\h -> getCompose . g (Compose . h))))
data HFree h t a
= HPure (t a)
| HWrap (h (HFree h t) a)
deriving (Typeable)
instance HFunctor h => HFunctor (HFree h) where
hmap = hliftM
instance HPointed (HFree h) where
hpure = HPure
instance HFunctor h => HBind (HFree h) where
HPure x ^>>= f = f x
HWrap x ^>>= f = HWrap (hmap (^>>= f) x)
instance HFunctor h => HMonad (HFree h)
instance (HFoldableAt k h) => HFoldableAt k (HFree h) where
hfoldMap f = \case
HPure x -> f x
HWrap x -> hfoldMap (hfoldMap f) x
instance HDuofoldableAt k HFree where
hduofoldMap g f = \case
HPure x -> f x
HWrap x -> g (hduofoldMap g f) x
instance HTraversable h => HTraversable (HFree h) where
htraverse f = \case
HPure x -> HPure <$> f x
HWrap x -> HWrap <$> htraverse (htraverse f) x
instance HDuofunctor HFree
instance HDuotraversable HFree where
hduotraverse g f = \case
HPure x -> HPure <$> f x
HWrap x -> HWrap <$> g (hduotraverse g f) x
instance (Functor f) => HFunctor (Compose f) where
hmap f = Compose . fmap f . getCompose
instance (Applicative f) => HPointed (Compose f) where
hpure = Compose . pure
instance (Monad f) => HBind (Compose f) where
Compose x ^>>= f = Compose (x >>= getCompose . f)
instance (Traversable f) => HTraversable (Compose f) where
htraverse f = fmap Compose . traverse f . getCompose
instance (Alternative g, Foldable f) => HFoldableAt g (Compose f) where
hfoldMap f = getAlt . foldMap (Alt . f) . getCompose
instance HFunctor (Product f)
instance HTraversable (Product f) where
htraverse f (Pair x y) = Pair x <$> f y
instance HBifunctor Product
instance HBitraversable Product where
hbitraverse f g (Pair x y) = Pair <$> f x <*> g y
instance (Alternative k) => HBifoldableAt k Product where
hbifoldMap f g (Pair x y) = f x <|> g y
instance (Alternative k) => HFoldableAt k (Product k) where
hfoldMap = hbifoldMap id
instance HFunctor Reverse
instance HTraversable Reverse where
htraverse f (Reverse x) = Reverse <$> f x
instance HPointed Reverse where
hpure = Reverse
instance HBind Reverse where
Reverse x ^>>= f = f x
instance HMonad Reverse
instance HFoldableAt k Reverse where
hfoldMap f (Reverse x) = f x
instance HFunctor (Sum f)
instance HTraversable (Sum f) where
htraverse _ (InL x) = pure (InL x)
htraverse f (InR y) = InR <$> f y
instance HBifunctor Sum
instance HBitraversable Sum where
hbitraverse f _ (InL x) = InL <$> f x
hbitraverse _ g (InR y) = InR <$> g y
instance HPointed (Sum f) where
hpure = InR
instance HBind (Sum f) where
InL x ^>>= _ = InL x
InR y ^>>= f = f y
instance HMonad (Sum f)
instance HBifoldableAt k Sum where
hbifoldMap f _ (InL x) = f x
hbifoldMap _ g (InR y) = g y
instance HFoldableAt k (Sum k) where
hfoldMap = hbifoldMap id
instance HFunctor (S.StateT s) where
hmap f (S.StateT k) = S.StateT (f . k)
instance HFunctor (L.StateT s) where
hmap f (L.StateT k) = L.StateT (f . k)
instance HFunctor (S.WriterT w) where
hmap f (S.WriterT x) = S.WriterT (f x)
instance HFunctor (L.WriterT w) where
hmap f (L.WriterT x) = L.WriterT (f x)
instance HFunctor (ReaderT r) where
hmap f (ReaderT k) = ReaderT (f . k)
instance HPointed (ReaderT r) where
hpure = ReaderT . const
instance HBind (ReaderT r) where
ReaderT k ^>>= f = ReaderT (\r -> runReaderT (f (k r)) r)
instance HMonad (ReaderT r)
instance HFunctor (ExceptT e) where
hmap f (ExceptT x) = ExceptT (f x)