{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Module: Semigroupoids.Do
-- Copyright: (C) Koz Ross 2021
-- License: Apache 2.0
-- Maintainer: koz.ross@retro-freedom.nz
-- Stability: Experimental
-- Portability: GHC only
--
-- Provides definitions needed to use do-notation (by way of @QualifiedDo@)
-- using the more general type classes provided by @semigroupoids@.
--
-- To use this module, enable @QualifiedDo@, import this module qualified, and
-- then prefix @do@ with the qualified name:
--
-- > {-# LANGUAGE QualifiedDo #-}
-- >
-- > module MyModule where
-- >
-- > import Data.Functor.Bind (Bind)
-- > import qualified Semigroupoids.Do as S
-- >
-- > foo :: (Bind m) => m a
-- > foo = S.do
-- > ...
--
-- This module is designed to work correctly (and similarly generally) with
-- @ApplicativeDo@ and @RecursiveDo@ (inasfar as that is possible).
module Semigroupoids.Do
( (>>=),
(>>),
fail,
fmap,
(<*>),
join,
mfix,
return,
)
where
import Control.Monad.Fix (mfix)
import Data.Functor.Apply (Apply ((<.>)))
import Data.Functor.Bind (Bind ((>>-)))
import qualified Data.Functor.Bind as Bind
import Data.Functor.Plus (Plus (zero))
import Data.Kind (Type)
import Prelude hiding
( fail,
return,
(<*>),
(>>),
(>>=),
)
-- | @since 1.0
(>>=) ::
forall (m :: Type -> Type) (a :: Type) (b :: Type).
(Bind m) =>
m a ->
(a -> m b) ->
m b
(>>=) = (>>-)
-- | @since 1.0
(>>) ::
forall (m :: Type -> Type) (a :: Type) (b :: Type).
(Bind m) =>
m a ->
m b ->
m b
x >> y = x >>- const y
-- | = Important note
--
-- This /ignores/ whatever 'String' you give it. It is a bad idea to use 'fail'
-- as a form of labelled error; instead, it should only be defaulted to when a
-- pattern match fails.
--
-- @since 1.0
fail ::
forall (m :: Type -> Type) (a :: Type).
(Plus m) =>
String ->
m a
fail _ = zero
-- | @since 1.0
(<*>) ::
forall (f :: Type -> Type) (a :: Type) (b :: Type).
(Apply f) =>
f (a -> b) ->
f a ->
f b
(<*>) = (<.>)
-- | @since 1.0
join ::
forall (m :: Type -> Type) (a :: Type).
(Bind m) =>
m (m a) ->
m a
join = Bind.join
-- | @since 1.0
return ::
forall (f :: Type -> Type) (a :: Type).
(Applicative f) =>
a ->
f a
return = pure