purescript-contrib / purescript-fork

An MTL-style class for monads that support forking
Apache License 2.0
8 stars 6 forks source link

Instanes for ExceptT? #7

Open safareli opened 6 years ago

safareli commented 6 years ago

I tried to implement some of this classes with ExceptT

MonadFork with Compose (Aff.Fiber eff) (Either MyError) as fiber could be implemented just fine

data MyError = MyCustomError

newtype M eff a = M (ExceptT MyError (Aff.Aff eff) a)

runM :: forall eff a. M eff a -> Aff.Aff eff (Either MyError a)
runM (M (ExceptT x)) = x

derive newtype instance functorM :: Functor (M e)
derive newtype instance applyM :: Apply (M e)
derive newtype instance applicativeM :: Applicative (M e)
derive newtype instance bindM :: Bind (M e)
derive newtype instance monadM :: Monad (M e)
derive newtype instance monadEffM :: MonadEff e (M e)
derive newtype instance monadAffM ∷ MonadAff e (M e)

instance monadForkM ∷ MonadFork (Compose (Aff.Fiber eff) (Either MyError)) (M eff) where
  suspend x = map Compose $ liftAff $ suspend $ runM x
  fork x = map Compose $ liftAff $ fork $ runM x
  join (Compose f) = M $ ExceptT $ join f

for MonadKill you need MonadThrow, i tried to implement it with Either MyError Aff.Error as error type, but i still have to do kill (Aff.error "kill") as in that case there is no Error around:

instance monadThrowM :: MonadThrow (Either MyError Aff.Error) (M e) where
  throwError (Left e) = M $ ExceptT $ pure $ Left e
  throwError (Right e) = M $ ExceptT $ throwError e

instance monadKillM ∷ MonadKill (Either MyError Aff.Error) (Compose (Aff.Fiber eff) (Either MyError)) (M eff) where
  kill (Left e) (Compose f) = M $ ExceptT $ kill (Aff.error "kill") f $> Left e
  kill (Right e) (Compose f) = M $ ExceptT $ map Right $ kill e f

for MonadBracket we need MonadError:

instance monadErrorM :: MonadError (Either MyError Aff.Error) (M e) where
  catchError x f = do
    res <- M $ ExceptT $ map Right $ Aff.try (runM x)
    case res of
      Left e -> f $ Right e
      Right (Left e) -> f $ Left e
      Right (Right a) -> pure a

But I got stack with bracket function of MonadBracket (uninterruptible and never are trivial to implement).

is it possible to implement correct bracket instance for ExceptT at all?

What should you do if you want some error type in your monad other then Error, is there some way which makes it possible to implement MonadBracket but still have custom error type?