These arrows don't make much sense to me:
stdoutProcessA :: Kleisli Maybe String (IO String)
writeToFileA :: Kleisli Maybe (FilePath, String) (IO ())
They represent functions with result Maybe (IO a)
, when you probably meant IO (Maybe a)
. The latter type represents IO
actions which may fail, while in the former the failure or success cannot depend on the IO
at all.
The correct way to combine IO
and Maybe
is to use the MaybeT
monad transformer, like so:
stdoutProcessA :: Kleisli (MaybeT IO) String String
writeToFileA :: Kleisli (MaybeT IO) (FilePath, String) ()
If you write your other arrows as Monad m => Kleisli (MaybeT m) a b
, they should compose nicely with these ones without any lifting. Alternatively, you can use
lift' :: Monad m => Kleisli Maybe a b -> Kleisli (MaybeT m) a b
lift' (Kleisli f) = Kleisli $ \x -> MaybeT (return $ f x)
to lift your existing Kleisli Maybe
arrows to Kleisli (MaybeT IO)
where needed.