将Kleisli箭头升入IO?

Phi*_*sky 3 io haskell arrows lifting kleisli

如果我有以下两个Kleisli箭头:

stdoutProcessA :: Kleisli Maybe String (IO String)
writeToFileA :: Kleisli Maybe (FilePath, String) (IO ())
Run Code Online (Sandbox Code Playgroud)

我希望能够写出像:

compile = proc src -> do
    output <- stdoutProcessA -< "..."
    writeToFileA -< ("...", output)
    ...
Run Code Online (Sandbox Code Playgroud)

这当然不起作用,因为String不匹配IO String.另一方面,可以定义两者stdoutProcessAwriteToFileA类型Kleisli IO ...,但是我不能用类型的箭头组合它们Kleisli Maybe ...,这是我需要的其他东西.

我对箭头还不是很有经验,所以我可能会遗漏一些明显的东西.如何进行上述操作?

ham*_*mar 5

这些箭对我来说没什么意义:

stdoutProcessA :: Kleisli Maybe String (IO String)
writeToFileA :: Kleisli Maybe (FilePath, String) (IO ())
Run Code Online (Sandbox Code Playgroud)

Maybe (IO a)当你可能意味着它们代表具有结果的函数IO (Maybe a).后一种类型代表IO可能失败的行为,而在前者中,失败或成功不能完全依赖于此IO.

结合正确的方法IO,并Maybe是使用MaybeT单子转换,就像这样:

stdoutProcessA :: Kleisli (MaybeT IO) String String
writeToFileA :: Kleisli (MaybeT IO) (FilePath, String) ()
Run Code Online (Sandbox Code Playgroud)

如果你把你的其他箭头写成Monad m => Kleisli (MaybeT m) a b,它们应该很好地与这些箭头组合而不需要任何提升.或者,您可以使用

lift' :: Monad m => Kleisli Maybe a b -> Kleisli (MaybeT m) a b
lift' (Kleisli f) = Kleisli $ \x -> MaybeT (return $ f x)
Run Code Online (Sandbox Code Playgroud)

将现有Kleisli Maybe箭头提升到Kleisli (MaybeT IO)需要的位置.