{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}
module Control.Effect.Fail
( Fail(..)
, MonadFail(..)
, runFail
, FailC(..)
) where
import Control.Applicative (Alternative(..))
import Control.Effect.Carrier
import Control.Effect.Error
import Control.Effect.Sum
import Control.Monad (MonadPlus(..))
import Control.Monad.Fail
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Prelude hiding (fail)
newtype Fail (m :: * -> *) k = Fail String
deriving stock Functor
deriving anyclass (HFunctor, Effect)
runFail :: FailC m a -> m (Either String a)
runFail = runError . runFailC
newtype FailC m a = FailC { runFailC :: ErrorC String m a }
deriving newtype (Alternative, Applicative, Functor, Monad, MonadIO, MonadPlus, MonadTrans)
instance (Carrier sig m, Effect sig) => MonadFail (FailC m) where
fail s = FailC (throwError s)
{-# INLINE fail #-}
instance (Carrier sig m, Effect sig) => Carrier (Fail :+: sig) (FailC m) where
eff (L (Fail s)) = fail s
eff (R other) = FailC (eff (R (handleCoercible other)))
{-# INLINE eff #-}