Поднимите стрелу Клейсли в 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)
где необходимо.