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

-- External imports
import Control.Arrow     (ArrowLoop (..))
import Control.Monad.Fix (MonadFix)

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

-- | 'ArrowLoop' instance for MSFs. The monad must be an instance of
-- 'MonadFix'.
instance MonadFix m => ArrowLoop (MSF m) where
  loop :: MSF m (b, d) (c, d) -> MSF m b c
  loop :: MSF m (b, d) (c, d) -> MSF m b c
loop MSF m (b, d) (c, d)
sf = (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 -> do
              rec ((c
b, d
c), MSF m (b, d) (c, d)
sf') <- MSF m (b, d) (c, d) -> (b, d) -> m ((c, d), MSF m (b, d) (c, d))
forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF MSF m (b, d) (c, d)
sf (b
a, d
c)
              (c, MSF m b c) -> m (c, MSF m b c)
forall (m :: * -> *) a. Monad m => a -> m a
return (c
b, MSF m (b, d) (c, d) -> MSF m b c
forall (a :: * -> * -> *) b d c.
ArrowLoop a =>
a (b, d) (c, d) -> a b c
loop MSF m (b, d) (c, d)
sf')