{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | = The control functor hierarchy
--
-- The functors in this module are called control functors, which
-- are different from the data functors in @Data.Functor.Linear@.
--
-- This distinction and the use-cases of each group of functors is explained in
-- [this blog post](https://tweag.io/posts/2020-01-16-data-vs-control.html).
module Control.Functor.Linear
  ( -- * Control functor hierarchy
    Functor (..),
    (<$>),
    (<&>),
    (<$),
    void,
    dataFmapDefault,
    Applicative (..),
    dataPureDefault,
    Monad (..),
    return,
    join,
    ap,
    foldM,
    MonadFail (..),
    Data (..),

    -- * Monad transformers

    -- ** ReaderT monad transformer
    -- $readerT
    Reader,
    reader,
    runReader,
    mapReader,
    withReader,
    ReaderT (..),
    runReaderT,
    mapReaderT,
    withReaderT,
    ask,
    local,
    asks,

    -- ** StateT monad
    -- $stateT
    State,
    state,
    runState,
    evalState,
    execState,
    mapState,
    withState,
    StateT (..),
    runStateT,
    evalStateT,
    execStateT,
    mapStateT,
    withStateT,
    get,
    put,
    modify,
    gets,
    MonadTrans (..),
    module Control.Functor.Linear.Internal.Instances,
  )
where

import Control.Functor.Linear.Internal.Class
import Control.Functor.Linear.Internal.Instances
import Control.Functor.Linear.Internal.MonadTrans
import Control.Functor.Linear.Internal.Reader
import Control.Functor.Linear.Internal.State

-- $readerT
-- See [here](https://mmhaskell.com/monads/reader-writer) to learn about
-- the basics of reader monads. To know about the standard reader monad
-- functions, see the documentation of the standard reader monad
-- [here](https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html).

-- $stateT
-- This is a linear version of the standard state monad.
-- The linear arrows ensure that the state is threaded linearly through
-- functions of the form @a %1-> StateT s m a@. That is, when sequencing
-- @f :: a %1-> StateT s m b@ and @g :: b %1-> StateT s m c@,
-- the type system enforces that state produced by $f$ is fed into @g@.
--
-- For this reason, there is only one way to define '(>>=)':
--
-- > instance Monad m => Applicative (StateT s m) where
-- > StateT mx >>= f = StateT $ \s -> do
-- >   (x, s') <- mx s
-- >   runStateT (f x) s'
--
-- To see examples and learn about all the standard state monad functions, see
-- [here](https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html).
-- To learn the basics of the state monad, see
-- [here](https://mmhaskell.com/monads/state).