{-# OPTIONS_HADDOCK hide #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LinearTypes #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeApplications #-} module Data.Functor.Linear.Internal.Traversable ( -- * Linear traversable hierarchy -- $ traversable Traversable(..) , mapM, sequenceA, for, forM , mapAccumL, mapAccumR ) where import qualified Control.Functor.Linear.Internal.Class as Control import qualified Control.Functor.Linear.Internal.State as Control import qualified Control.Functor.Linear.Internal.Instances as Control import qualified Data.Functor.Linear.Internal.Functor as Data import qualified Data.Functor.Linear.Internal.Applicative as Data import Data.Functor.Const import Prelude.Linear.Internal import Prelude (Maybe(..), Either(..)) -- $traversable -- TODO: write the laws -- TODO: maybe add a Foldable class between Functor and Traversable as well -- | A linear data traversible is a functor of type @t a@ where you can apply a -- linear effectful action of type @a %1-> f b@ on each value of type @a@ and -- compose this to perform an action on the whole functor, resulting in a value -- of type @f (t b)@. -- -- To learn more about 'Traversable', see here: -- -- * \"Applicative Programming with Effects\", -- by Conor McBride and Ross Paterson, -- /Journal of Functional Programming/ 18:1 (2008) 1-13, online at -- . -- -- * \"The Essence of the Iterator Pattern\", -- by Jeremy Gibbons and Bruno Oliveira, -- in /Mathematically-Structured Functional Programming/, 2006, online at -- . -- -- * \"An Investigation of the Laws of Traversals\", -- by Mauro Jaskelioff and Ondrej Rypacek, -- in /Mathematically-Structured Functional Programming/, 2012, online at -- . -- class Data.Functor t => Traversable t where {-# MINIMAL traverse | sequence #-} traverse :: Control.Applicative f => (a %1-> f b) -> t a %1-> f (t b) {-# INLINE traverse #-} traverse f x = sequence (Data.fmap f x) sequence :: Control.Applicative f => t (f a) %1-> f (t a) {-# INLINE sequence #-} sequence = traverse id mapM :: (Traversable t, Control.Monad m) => (a %1-> m b) -> t a %1-> m (t b) mapM = traverse {-# INLINE mapM #-} sequenceA :: (Traversable t, Control.Applicative f) => t (f a) %1-> f (t a) sequenceA = sequence {-# INLINE sequenceA #-} for :: (Traversable t, Control.Applicative f) => t a %1-> (a %1-> f b) -> f (t b) for t f = traverse f t {-# INLINE for #-} forM :: (Traversable t, Control.Monad m) => t a %1-> (a %1-> m b) -> m (t b) forM = for {-# INLINE forM #-} mapAccumL :: Traversable t => (a %1-> b %1-> (a,c)) -> a %1-> t b %1-> (a, t c) mapAccumL f s t = swap $ Control.runState (traverse (\b -> Control.state $ \i -> swap $ f i b) t) s mapAccumR :: Traversable t => (a %1-> b %1-> (a,c)) -> a %1-> t b %1-> (a, t c) mapAccumR f s t = swap $ runStateR (traverse (\b -> StateR $ \i -> swap $ f i b) t) s swap :: (a,b) %1-> (b,a) swap (x,y) = (y,x) -- | A right-to-left state transformer newtype StateR s a = StateR (s %1-> (a, s)) deriving (Data.Functor, Data.Applicative) via Control.Data (StateR s) runStateR :: StateR s a %1-> s %1-> (a, s) runStateR (StateR f) = f instance Control.Functor (StateR s) where fmap f (StateR x) = StateR $ (\(a, s') -> (f a, s')) . x instance Control.Applicative (StateR s) where pure x = StateR $ \s -> (x,s) StateR f <*> StateR x = StateR (go . Control.fmap f . x) where go :: (a, (a %1-> b, s)) %1-> (b, s) go (a, (h, s'')) = (h a, s'') ------------------------ -- Standard instances -- ------------------------ instance Traversable [] where traverse _f [] = Control.pure [] traverse f (a : as) = (:) Control.<$> f a Control.<*> traverse f as instance Traversable ((,) a) where sequence (a, fb) = (a,) Control.<$> fb instance Traversable Maybe where sequence Nothing = Control.pure Nothing sequence (Just x) = Control.fmap Just x instance Traversable (Const a) where sequence (Const x) = Control.pure (Const x) instance Traversable (Either a) where sequence (Left x) = Control.pure (Left x) sequence (Right x) = Right Control.<$> x