{-# OPTIONS_GHC -fno-warn-orphans #-}
-- |
-- Copyright  : (c) Ivan Perez and Manuel Baerenz, 2016
-- License    : BSD3
-- Maintainer : ivan.perez@keera.co.uk
--
-- Instance of 'ArrowPlus' for Monadic Stream Functions ('MSF').
--
-- Import this module to include that (orphan) instance.
--
-- This is only defined for monads that are instances of 'MonadPlus'.
module Data.MonadicStreamFunction.Instances.ArrowPlus where

-- External imports
import Control.Applicative (Alternative (..))
import Control.Arrow       (ArrowPlus (..), ArrowZero (..))
import Control.Monad       (MonadPlus, mplus, mzero)

-- Internal imports
import Data.MonadicStreamFunction.Core         ()
import Data.MonadicStreamFunction.InternalCore (MSF (MSF, unMSF))

-- | Instance of 'ArrowZero' for Monadic Stream Functions ('MSF'). The monad
-- must be an instance of 'MonadPlus'.
instance (Monad m, MonadPlus m) => ArrowZero (MSF m) where
  zeroArrow :: forall b c. MSF m b c
zeroArrow = (b -> m (c, MSF m b c)) -> MSF m b c
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((b -> m (c, MSF m b c)) -> MSF m b c)
-> (b -> m (c, MSF m b c)) -> MSF m b c
forall a b. (a -> b) -> a -> b
$ m (c, MSF m b c) -> b -> m (c, MSF m b c)
forall a b. a -> b -> a
const m (c, MSF m b c)
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | Instance of 'ArrowPlus' for Monadic Stream Functions ('MSF'). The monad
-- must be an instance of 'MonadPlus'.
instance (Monad m, MonadPlus m) => ArrowPlus (MSF m) where
  MSF m b c
sf1 <+> :: forall b c. MSF m b c -> MSF m b c -> MSF m b c
<+> MSF m b c
sf2 = (b -> m (c, MSF m b c)) -> MSF m b c
forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b
MSF ((b -> m (c, MSF m b c)) -> MSF m b c)
-> (b -> m (c, MSF m b c)) -> MSF m b c
forall a b. (a -> b) -> a -> b
$ \b
a -> MSF m b c -> b -> m (c, MSF m b c)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF MSF m b c
sf1 b
a m (c, MSF m b c) -> m (c, MSF m b c) -> m (c, MSF m b c)
forall a. m a -> m a -> m a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` MSF m b c -> b -> m (c, MSF m b c)
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF MSF m b c
sf2 b
a

-- | Instance of 'Alternative' for Monadic Stream Functions ('MSF'),
-- implemented using the 'ArrowZero' and 'ArrowPlus' instances.
instance (Functor m, Monad m, MonadPlus m) => Alternative (MSF m a) where
  empty :: forall a. MSF m a a
empty = MSF m a a
forall b c. MSF m b c
forall (a :: * -> * -> *) b c. ArrowZero a => a b c
zeroArrow
  <|> :: forall a. MSF m a a -> MSF m a a -> MSF m a a
(<|>) = MSF m a a -> MSF m a a -> MSF m a a
forall b c. MSF m b c -> MSF m b c -> MSF m b c
forall (a :: * -> * -> *) b c.
ArrowPlus a =>
a b c -> a b c -> a b c
(<+>)