Поднимите стрелу Клейсли в IO?

Если у меня есть следующие две стрелки Клейсли:

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

Я хотел бы иметь возможность написать что-то вроде:

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

что, конечно, не работает, потому что String не совпадает с IO String, С другой стороны, можно определить как stdoutProcessA а также writeToFileA быть типом Kleisli IO ..., но тогда я не смог бы составить их со стрелками типа Kleisli Maybe ..., который мне нужен для других вещей.

Я еще не очень разбираюсь со стрелами, поэтому я, вероятно, упускаю что-то очевидное Как можно поступить с этим?

1 ответ

Решение

Эти стрелки не имеют большого смысла для меня:

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

Они представляют функции с результатом Maybe (IO a)когда вы, вероятно, имели в виду IO (Maybe a), Последний тип представляет IO действия, которые могут потерпеть неудачу, в то время как в первом случае неудача или успех не могут зависеть от IO совсем.

Правильный способ комбинировать IO а также Maybe это использовать MaybeT Монадный трансформатор, вот так:

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) где необходимо.

Другие вопросы по тегам