folds-0.3: src/Data/Fold/R.hs
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ExistentialQuantification #-}
module Data.Fold.R
( R(..)
) where
import Control.Applicative
import Control.Comonad
import Control.Lens
import Data.Foldable hiding (sum, product)
import Data.Fold.Class
import Data.Fold.Internal
import Data.Functor.Extend
import Data.Functor.Bind
import Data.Profunctor.Unsafe
import Unsafe.Coerce
import Prelude hiding (foldr, sum, product, length)
-- | right folds / a reversed Moore machine
data R a b = forall r. R (r -> b) (a -> r -> r) r
instance Scan R where
run1 t (R k h z) = k (h t z)
prefix1 a = extend (run1 a)
postfix1 t a = run1 a (duplicate t)
interspersing a (R k h z) = R (maybe' (k z) k) h' Nothing' where
h' b Nothing' = Just' (h b z)
h' b (Just' x) = Just' (h b (h a x))
{-# INLINE run1 #-}
{-# INLINE prefix1 #-}
{-# INLINE postfix1 #-}
{-# INLINE interspersing #-}
-- | leaky 'prefix', efficient 'postfix'
instance Folding R where
run t (R k h z) = k (foldr h z t)
runOf l s (R k h z) = k (foldrOf l h z s)
prefix s = extend (run s)
prefixOf l s = extend (runOf l s)
postfix t s = run s (duplicate t)
postfixOf l t s = runOf l s (duplicate t)
filtering p (R k h z) = R k (\a r -> if p a then h a r else r) z
{-# INLINE run #-}
{-# INLINE runOf #-}
{-# INLINE prefix #-}
{-# INLINE prefixOf #-}
{-# INLINE postfix #-}
{-# INLINE postfixOf #-}
{-# INLINE filtering #-}
instance Profunctor R where
dimap f g (R k h z) = R (g.k) (h.f) z
{-# INLINE dimap #-}
rmap g (R k h z) = R (g.k) h z
{-# INLINE rmap #-}
lmap f (R k h z) = R k (h.f) z
{-# INLINE lmap #-}
(#.) _ = unsafeCoerce
{-# INLINE (#.) #-}
x .# _ = unsafeCoerce x
{-# INLINE (.#) #-}
instance Choice R where
left' (R k h z) = R (_Left %~ k) step (Left z) where
step (Left x) (Left y) = Left (h x y)
step (Right c) _ = Right c
step _ (Right c) = Right c
{-# INLINE left' #-}
right' (R k h z) = R (_Right %~ k) step (Right z) where
step (Right x) (Right y) = Right (h x y)
step (Left c) _ = Left c
step _ (Left c) = Left c
{-# INLINE right' #-}
instance Functor (R a) where
fmap f (R k h z) = R (f.k) h z
{-# INLINE fmap #-}
(<$) b = \_ -> pure b
{-# INLINE (<$) #-}
instance Comonad (R a) where
extract (R k _ z) = k z
{-# INLINE extract #-}
duplicate (R k h z) = R (R k h) h z
{-# INLINE duplicate #-}
extend f (R k h z) = R (f . R k h) h z
{-# INLINE extend #-}
instance Bind (R a) where
(>>-) = (>>=)
{-# INLINE (>>-) #-}
instance Monad (R a) where
return b = R (\() -> b) (\_ () -> ()) ()
{-# INLINE return #-}
m >>= f = R (\xs a -> run xs (f a)) (:) [] <*> m
{-# INLINE (>>=) #-}
_ >> n = n
{-# INLINE (>>) #-}
instance Applicative (R a) where
pure b = R (\() -> b) (\_ () -> ()) ()
{-# INLINE pure #-}
R xf bxx xz <*> R ya byy yz = R
(\(Pair' x y) -> xf x $ ya y)
(\b (Pair' x y) -> Pair' (bxx b x) (byy b y))
(Pair' xz yz)
{-# INLINE (<*>) #-}
(<*) m = \_ -> m
{-# INLINE (<*) #-}
_ *> m = m
{-# INLINE (*>) #-}
instance Extend (R a) where
extended = extend
{-# INLINE extended #-}
duplicated = duplicate
{-# INLINE duplicated #-}
instance Apply (R a) where
(<.>) = (<*>)
{-# INLINE (<.>) #-}
(<.) m = \_ -> m
{-# INLINE (<.) #-}
_ .> m = m
{-# INLINE (.>) #-}
instance ComonadApply (R a) where
(<@>) = (<*>)
{-# INLINE (<@>) #-}
(<@) m = \_ -> m
{-# INLINE (<@) #-}
_ @> m = m
{-# INLINE (@>) #-}