module Hask.Foldable where
import qualified Control.Applicative as Base
import qualified Data.Foldable as Base
import qualified Data.Functor as Base
import qualified Data.Monoid as Base
import qualified Data.Traversable as Base
import Hask.Core
import Hask.Power
class Functor f => Foldable (f :: i -> j) where
foldMap :: Monoid (m :: j) => (a ⋔ m) ~> (f a ⋔ m)
newtype WrapMonoid m = WrapMonoid { runWrapMonoid :: m }
instance Monoid m => Base.Monoid (WrapMonoid m) where
mempty = WrapMonoid (one ())
mappend (WrapMonoid a) (WrapMonoid b) = WrapMonoid (mult (a, b))
foldMapHask :: (Base.Foldable f, Monoid m) => (a -> m) -> f a -> m
foldMapHask f = runWrapMonoid . Base.foldMap (WrapMonoid . f)
instance Foldable [] where foldMap = foldMapHask
instance Foldable Maybe where foldMap = foldMapHask
instance Foldable (,) where
foldMap = Nat $ \f -> Lift $ runPower f . fst
instance Foldable ((,) e) where foldMap = lmap snd
instance Foldable Either where
foldMap = Nat $ \f -> Lift $ (runPower f ||| \ _ -> runNat one (Const ()))
instance Foldable (Either a) where foldMap = foldMapHask
instance Foldable ((&) e) where foldMap = lmap snd
instance Foldable (Lift1 (,) e) where foldMap = lmap snd
instance Foldable (Lift2 (Lift1 (,)) e) where foldMap = lmap snd
instance Foldable (Lift1 Either e) where
foldMap = Nat $ \ f -> Lift $ \case
Lift (Left _) -> runNat one (Const ())
Lift (Right e) -> lower f e
instance Foldable (Lift2 (Lift1 Either) e) where
foldMap = nat2 $ \ (Lift2 (Lift f)) -> Lift2 $ Lift $ \case
Lift2 (Lift (Left _)) -> runNat2 one (Const2 (Const ()))
Lift2 (Lift (Right e)) -> f e
class Functor f => Traversable f where
traverse :: Monoidal m => (a ~> m b) -> f a ~> m (f b)
newtype WrapMonoidal f a = WrapMonoidal { runWrapMonoidal :: f a }
_WrapMonoidal = dimap runWrapMonoidal WrapMonoidal
instance Functor f => Base.Functor (WrapMonoidal f) where
fmap f (WrapMonoidal m) = WrapMonoidal (fmap f m)
instance Monoidal f => Base.Applicative (WrapMonoidal f) where
pure a = WrapMonoidal (return a)
WrapMonoidal f <*> WrapMonoidal g = WrapMonoidal $ ap f g
fmapDefault f = get _Id . traverse (beget _Id . f)
foldMapDefault f = get _Const . traverse (beget _Const . f)
traverseHask :: (Base.Traversable f, Monoidal m) => (a -> m b) -> f a -> m (f b)
traverseHask f = runWrapMonoidal . Base.traverse (WrapMonoidal . f)
instance Traversable [] where traverse = traverseHask
instance Traversable Maybe where traverse = traverseHask
instance Traversable (Either a) where traverse = traverseHask
instance Traversable ((,) e) where traverse = traverseHask