Какова цель трансформатора IdentityT?
Просматривая пакет трансформаторов, я нашел этот монадный трансформатор под названием IdentityT.
Хотя я понимаю, как используется монада Identity (например, State
является просто псевдонимом для StateT Identity
) и как работают монадные трансформаторы вообще, я не знаю, как это относится к IdentityT
.
Поскольку это не в MTL, я предполагаю, что он был добавлен там только для полноты и не имеет практического применения. Это правильно?
Ответы
Ответ 1
Хорошо связанная документация говорит
Это полезно для функций, параметризованных монадным трансформатором.
Хотя я не знаю ни о каких ситуациях, где это на самом деле. Теоретически, если у вас есть такая функция, как foo :: (MonadTrans t, Monad m) => t m a -> b
для некоторого полезного b
, то вы можете захотеть "опустить ее вниз" по существу m a -> b
с помощью t = IdentityT
.
Но IdentityT
соответствует MonadTrans
, что Identity
соответствует Monad
. Это "проходной" трансформатор, поскольку Identity
является "проходной" монадой. Просто проверьте источник; это довольно просто. IdentityT SomeMonad a
должен вести себя одинаково с SomeMonad a
, с той лишь разницей, что существует дополнительный тип newtype (который, конечно же, удаляется во время компиляции)
Ответ 2
Здесь предлагается использовать (предположительно, источник IdentityT:
http://www.haskell.org/pipermail/libraries/2007-June/007563.html
Основное использование, по-видимому, заключается в обеспечении гибкости на уровне исходного кода, например. кто-то может отредактировать источник на xmonad и заменить свой собственный UserT без редактирования слишком большого кода.
Я попытался понять, как это может работать для библиотеки - вы можете использовать его, чтобы предоставить местозаполнитель для вставки монады в середине стека, но я не уверен в этом. Вот мой надуманный пример:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main where
import Control.Monad.State
import Control.Monad.List
import Control.Monad.Reader
type X m a = StateT Int (m IO) a
something :: (Monad (m IO), MonadIO (m IO)) => (m IO) Int -> X m Int
something a = do
x <- lift a
put (x + 1)
liftIO $ print x
return x
listSomething = something $ ListT (mapM return [1,2,3,4])
plainSomething = return 5 :: IdentityT IO Int
main = do
x <- runListT (execStateT listSomething 3)
print x
y <- runIdentityT (execStateT plainSomething 3)
print y
runIdentity $ mapM (return . (+1)) [1..100]