folds-0.7.8: src/Data/Fold/Internal.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Fold.Internal
( SnocList(..)
, SnocList1(..)
, List1(..)
, Maybe'(..), maybe'
, Pair'(..)
, N(..)
, S(..)
, Tree(..)
, Tree1(..)
, An(..)
, Box(..)
, FreeMonoid(..)
, foldDeRef
, FreeSemigroup(..)
, foldDeRef1
) where
import Control.Monad.Fix
import Data.Bifunctor
import Data.Bifoldable
import Data.Bitraversable
import Data.Constraint
import Data.Data (Data)
import Data.Kind
import Data.Semigroup hiding (Last, First)
import Data.Functor.Bind
import Data.HashMap.Lazy as HM
import Data.Profunctor.Unsafe
import Data.Proxy (Proxy(Proxy))
import Data.Reflection
import Data.Reify
import Data.Semigroup.Foldable
import Data.Semigroup.Bifoldable
import Data.Semigroup.Bitraversable
import System.IO.Unsafe
-- | Reversed '[]'
data SnocList a = Snoc (SnocList a) a | Nil
deriving (Eq,Ord,Show,Read,Data)
instance Functor SnocList where
fmap f (Snoc xs x) = Snoc (fmap f xs) (f x)
fmap _ Nil = Nil
{-# INLINABLE fmap #-}
instance Foldable SnocList where
foldl f z m0 = go m0 where
go (Snoc xs x) = f (go xs) x
go Nil = z
{-# INLINE foldl #-}
foldMap f (Snoc xs x) = foldMap f xs `mappend` f x
foldMap _ Nil = mempty
{-# INLINABLE foldMap #-}
instance Traversable SnocList where
traverse f (Snoc xs x) = Snoc <$> traverse f xs <*> f x
traverse _ Nil = pure Nil
{-# INLINABLE traverse #-}
data SnocList1 a = Snoc1 (SnocList1 a) a | First a
deriving (Eq,Ord,Show,Read,Data)
instance Functor SnocList1 where
fmap f (Snoc1 xs x) = Snoc1 (fmap f xs) (f x)
fmap f (First a) = First (f a)
{-# INLINABLE fmap #-}
instance Foldable SnocList1 where
foldl f z m0 = go m0 where
go (Snoc1 xs x) = f (go xs) x
go (First a) = f z a
{-# INLINE foldl #-}
foldl1 f m0 = go m0 where
go (Snoc1 xs x) = f (go xs) x
go (First a) = a
{-# INLINE foldl1 #-}
foldMap f (Snoc1 xs x) = foldMap f xs `mappend` f x
foldMap f (First a) = f a
{-# INLINABLE foldMap #-}
instance Traversable SnocList1 where
traverse f (Snoc1 xs x) = Snoc1 <$> traverse f xs <*> f x
traverse f (First a) = First <$> f a
{-# INLINABLE traverse #-}
-- | Strict 'Maybe'
data Maybe' a = Nothing' | Just' !a
deriving (Eq,Ord,Show,Read,Data)
instance Foldable Maybe' where
foldMap _ Nothing' = mempty
foldMap f (Just' a) = f a
maybe' :: b -> (a -> b) -> Maybe' a -> b
maybe' _ f (Just' a) = f a
maybe' z _ Nothing' = z
{-# INLINE maybe' #-}
-- | A reified 'Monoid'.
newtype N a s = N { runN :: a }
deriving (Eq,Ord,Show,Read,Data)
instance Reifies s (a -> a -> a, a) => Semigroup (N a s) where
N a <> N b = N $ fst (reflect (Proxy :: Proxy s)) a b
{-# INLINE (<>) #-}
instance Reifies s (a -> a -> a, a) => Monoid (N a s) where
mempty = N $ snd $ reflect (Proxy :: Proxy s)
{-# INLINE mempty #-}
mappend = (<>)
{-# INLINE mappend #-}
-- | The shape of a 'foldMap'
data Tree a
= Zero
| One a
| Two (Tree a) (Tree a)
deriving (Eq,Ord,Show,Read,Data)
instance Functor Tree where
fmap _ Zero = Zero
fmap f (One a) = One (f a)
fmap f (Two a b) = Two (fmap f a) (fmap f b)
instance Foldable Tree where
foldMap _ Zero = mempty
foldMap f (One a) = f a
foldMap f (Two a b) = foldMap f a `mappend` foldMap f b
instance Traversable Tree where
traverse _ Zero = pure Zero
traverse f (One a) = One <$> f a
traverse f (Two a b) = Two <$> traverse f a <*> traverse f b
-- | A reified 'Semigroup'.
newtype S a s = S { runS :: a }
deriving (Eq,Ord,Show,Read,Data)
instance Reifies s (a -> a -> a) => Semigroup (S a s) where
S a <> S b = S $ reflect (Proxy :: Proxy s) a b
-- | Strict Pair
data Pair' a b = Pair' !a !b deriving (Eq,Ord,Show,Read,Data)
instance (Semigroup a, Semigroup b) => Semigroup (Pair' a b) where
Pair' a b <> Pair' c d = Pair' (a <> c) (b <> d)
{-# INLINE (<>) #-}
instance (Monoid a, Monoid b) => Monoid (Pair' a b) where
mempty = Pair' mempty mempty
{-# INLINE mempty #-}
#if !(MIN_VERSION_base(4,11,0))
mappend (Pair' a b) (Pair' c d) = Pair' (mappend a c) (mappend b d)
{-# INLINE mappend #-}
#endif
newtype An a = An a deriving (Eq,Ord,Show,Read,Data)
instance Functor An where
fmap f (An a) = An (f a)
instance Foldable An where
foldMap f (An a) = f a
instance Traversable An where
traverse f (An a) = An <$> f a
data Box a = Box a deriving (Eq,Ord,Show,Read,Data)
instance Functor Box where
fmap f (Box a) = Box (f a)
instance Foldable Box where
foldMap f (Box a) = f a
instance Traversable Box where
traverse f (Box a) = Box <$> f a
data List1 a = Cons1 a (List1 a) | Last a
instance Functor List1 where
fmap f (Cons1 a as) = Cons1 (f a) (fmap f as)
fmap f (Last a) = Last (f a)
instance Foldable List1 where
foldMap f = go where
go (Cons1 a as) = f a `mappend` foldMap f as
go (Last a) = f a
{-# INLINE foldMap #-}
foldr f z = go where
go (Cons1 a as) = f a (go as)
go (Last a) = f a z
{-# INLINE foldr #-}
foldr1 f = go where
go (Cons1 a as) = f a (go as)
go (Last a) = a
{-# INLINE foldr1 #-}
instance Traversable List1 where
traverse f (Cons1 a as) = Cons1 <$> f a <*> traverse f as
traverse f (Last a) = Last <$> f a
{-# INLINABLE traverse #-}
data Tree1 a = Bin1 (Tree1 a) (Tree1 a) | Tip1 a
instance Functor Tree1 where
fmap f (Bin1 as bs) = Bin1 (fmap f as) (fmap f bs)
fmap f (Tip1 a) = Tip1 (f a)
instance Foldable Tree1 where
foldMap f (Bin1 as bs) = foldMap f as `mappend` foldMap f bs
foldMap f (Tip1 a) = f a
instance Traversable Tree1 where
traverse f (Bin1 as bs) = Bin1 <$> traverse f as <*> traverse f bs
traverse f (Tip1 a) = Tip1 <$> f a
newtype FreeMonoid a = FreeMonoid { runFreeMonoid :: forall m. Monoid m => (a -> m) -> m } deriving Functor
instance Foldable FreeMonoid where
foldMap f m = runFreeMonoid m f
newtype FreeSemigroup a = FreeSemigroup { runFreeSemigroup :: forall m. Semigroup m => (a -> m) -> m } deriving Functor
instance Foldable FreeSemigroup where
foldMap f (FreeSemigroup m) = unwrapMonoid $ m (WrapMonoid #. f)
instance Foldable1 FreeSemigroup where
foldMap1 f (FreeSemigroup m) = m f
data T a b = T0 | T1 a | T2 b b deriving (Functor, Foldable, Traversable)
instance MuRef (Tree a) where
type DeRef (Tree a) = T a
mapDeRef _ Zero = pure T0
mapDeRef _ (One a) = pure (T1 a)
mapDeRef f (Two x y) = T2 <$> f x <*> f y
class MuRef1 (f :: Type -> Type) where
type DeRef1 f :: Type -> Type -> Type
muRef1 :: proxy (f a) -> Dict (MuRef (f a), DeRef (f a) ~ DeRef1 f a)
foldDeRef :: forall f a. (MuRef1 f, Bifoldable (DeRef1 f)) => f a -> FreeMonoid a
foldDeRef m = case muRef1 (undefined :: Proxy (f a)) of
Dict -> case unsafePerformIO (reifyGraph m) of
Graph xs i | hm <- HM.fromList xs -> FreeMonoid $ \ f -> fix (\mm -> fmap (bifoldMap f (mm !)) hm) ! i
instance MuRef1 Tree where
type DeRef1 Tree = T
muRef1 _ = Dict
instance Bifunctor T where
bimap _ _ T0 = T0
bimap f _ (T1 a) = T1 (f a)
bimap _ g (T2 b c) = T2 (g b) (g c)
instance Bifoldable T where
bifoldMap _ _ T0 = mempty
bifoldMap f _ (T1 a) = f a
bifoldMap _ g (T2 b c) = g b `mappend` g c
instance Bitraversable T where
bitraverse _ _ T0 = pure T0
bitraverse f _ (T1 a) = T1 <$> f a
bitraverse _ g (T2 b c) = T2 <$> g b <*> g c
data T1 a b = A a | B b b deriving (Functor, Foldable, Traversable)
instance MuRef (Tree1 a) where
type DeRef (Tree1 a) = T1 a
mapDeRef _ (Tip1 a) = pure (A a)
mapDeRef f (Bin1 b c) = B <$> f b <*> f c
instance MuRef1 Tree1 where
type DeRef1 Tree1 = T1
muRef1 _ = Dict
instance Bifunctor T1 where
bimap f _ (A a) = A (f a)
bimap _ g (B b c) = B (g b) (g c)
instance Bifoldable T1 where
bifoldMap f _ (A a) = f a
bifoldMap _ g (B b c) = g b `mappend` g c
instance Bitraversable T1 where
bitraverse f _ (A a) = A <$> f a
bitraverse _ g (B b c) = B <$> g b <*> g c
foldDeRef1 :: forall f a. (MuRef1 f, Bifoldable1 (DeRef1 f)) => f a -> FreeSemigroup a
foldDeRef1 m = case muRef1 (undefined :: Proxy (f a)) of
Dict -> case unsafePerformIO (reifyGraph m) of
Graph xs i | hm <- HM.fromList xs -> FreeSemigroup $ \ f -> fix (\mm -> fmap (bifoldMap1 f (mm !)) hm) ! i
instance Bifoldable1 T1 where
bifoldMap1 f _ (A a) = f a
bifoldMap1 _ g (B b c) = g b <> g c
instance Bitraversable1 T1 where
bitraverse1 f _ (A a) = A <$> f a
bitraverse1 _ g (B b c) = B <$> g b <.> g c