3

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

stdoutProcessA :: Kleisli Maybe String (IO String)
writeToFileA :: Kleisli Maybe (FilePath, String) (IO ())

我希望能够写出类似的东西:

compile = proc src -> do
    output <- stdoutProcessA -< "..."
    writeToFileA -< ("...", output)
    ...

这当然行不通,因为String不匹配IO String. 另一方面,可以同时定义stdoutProcessA和定义writeToFileAtype Kleisli IO ...,但是我将无法用 type 的箭头组合它们Kleisli Maybe ...,这是我需要的其他事情。

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

4

1 回答 1

5

这些箭头对我来说没有多大意义:

stdoutProcessA :: Kleisli Maybe String (IO String)
writeToFileA :: Kleisli Maybe (FilePath, String) (IO ())

Maybe (IO a)当您可能是指时,它们代表带有结果的函数IO (Maybe a)。后一种类型代表IO可能失败的动作,而在前一种中,失败或成功根本不取决于IO

IO组合and的正确方法Maybe是使用MaybeTmonad 转换器,如下所示:

stdoutProcessA :: Kleisli (MaybeT IO) String String
writeToFileA :: Kleisli (MaybeT IO) (FilePath, String) ()

如果您将其他箭头写为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)

将您现有的Kleisli Maybe箭头提升到Kleisli (MaybeT IO)需要的地方。

于 2012-11-22T01:54:53.937 回答