Скажем, у меня есть вычислениеКаков наилучший способ поддержки монадных трансформаторов в функциях, которые принимают монадические команды в качестве аргументов?
class A where
foo :: () -> ()
instance A IO where
foo x = do
print "prefix"
x
print "suffix"
Теперь предположим, что я хочу написать
instance A => A (MyMonadTransformerT γ)
Затем в реализации foo
, я вынужден «разворачивать» свой аргумент, например foo x = lift (foo (unlift x))
. Эта функция unlift
может быть плохой для монадических вычислений. Для трансформатора состояния он будет вынужден забыть о любых изменениях в состоянии программы.
Как представляется, для создания более общего метода, который также выполняет функцию подъема, и приводит к вычислению t() -> t()
, где t
является поднятой (траншейной) монадой.
class Monad => A' where
foo' :: Monad t =>
(forall z . z -> t z) -- lifting function
-> t()
-> t()
foo :: () -> ()
foo = foo' id
instance A' IO where
foo' lift x = do
lift (print "prefix")
x
lift (print "suffix")
instance A' => A' (StateT γ) where
foo' lift' x = foo' (lift' . lift) x
computation :: Num a => StateT a IO()
computation = do
foo (put 1 >> lift (print "middle"))
v <- get
lift $ print ("value", v)
run_computation :: Num a => IO a
run_computation = execStateT computation 0
Вопрос. Это лучший способ? Есть ли что-то более общее, что можно написать? Код в стиле CPS? Благодаря!!
Возможный дубликат [Подъем функции более высокого порядка в Haskell] (http://stackoverflow.com/questions/9243215/lifting-a-higher-order-function-in-haskell) –
Да, я думаю, что это дубликат , Подход «refying the class» I и luqui взял, кажется, самый приятный. – gatoatigrado