Непонятное название для сбивающего с толку вопроса! Я понимаю а) монады, б) монаду ввода-вывода, в) монаду Cont ( Control.Monad.Cont ), и d) монада преобразователя продолжения ContT . (И я смутно понимаю преобразователи монад в целом - хотя и недостаточно, чтобы ответить на этот вопрос.) Я понимаю, как написать программу, в которой все функции находятся в монаде Cont ( Cont ra
]), и я понимаю, как написать программу, в которой все функции находятся в объединенной монаде Cont / IO ( ContT r IO a
).
Но мне интересно как я мог бы написать программу, в которой некоторые функции находятся в комбинированной монаде Cont / IO ( ContT r IO a
), а другие функции находятся только в монаде Cont ( Контра
). По сути, я хочу написать всю программу в стиле продолжения, но использовать монаду ввода-вывода только там, где это необходимо (как и в «обычном» коде Haskell, я использую монаду ввода-вывода только там, где это необходимо).
Например, рассмотрим эти две функции , в стиле без продолжения:
foo :: Int -> IO Int
foo n = do
let x = n + 1
print x
return $ bar x
bar :: Int -> Int
bar m = m * 2
Обратите внимание, что foo
требует ввода-вывода, но bar
является чистым. Теперь я понял, как полностью написать этот код, используя монаду продолжения, но мне также нужно было пропустить ввод-вывод через bar
:
foo :: Int -> ContT r IO Int
foo n = do
let x = n + 1
liftIO $ print x
bar x
bar :: Int -> ContT r IO Int
bar m = return $ m * 2
Я действительно хочу, чтобы весь мой код был в стиле продолжения , но я не хочу использовать монаду ввода-вывода для функций, которым она не требуется. По сути, я хотел бы, чтобы определял bar
следующим образом:
bar :: Int -> Cont r Int
bar m = return $ m * 2
К сожалению, я не могу найти способ вызвать функцию монады Cont ra
( bar
) изнутри ContT r IO a
монадная функция ( foo
). Есть ли способ «поднять» нетрансформированную монаду в трансформированную? т.е.как мне изменить строку « bar x
» в foo
, чтобы она могла правильно вызывать bar :: Int -> Cont r Int
?