在查看 transformers 包时,我发现了这个名为IdentityT的 monad 转换器。
尽管我了解 Identity monad 的使用方式(例如State
只是 的别名StateT Identity
)以及 monad 转换器的一般工作方式,但我不知道这与IdentityT
.
由于它不在 MTL 中,我猜它只是为了完整性而添加在那里并且没有实际用途。那是对的吗?
在查看 transformers 包时,我发现了这个名为IdentityT的 monad 转换器。
尽管我了解 Identity monad 的使用方式(例如State
只是 的别名StateT Identity
)以及 monad 转换器的一般工作方式,但我不知道这与IdentityT
.
由于它不在 MTL 中,我猜它只是为了完整性而添加在那里并且没有实际用途。那是对的吗?
那么链接的文档确实说
这对于由 monad 转换器参数化的函数很有用。
尽管我不知道实际上是这种情况的任何情况。从理论上讲,如果您有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
,唯一的区别是存在额外的新类型(当然,在编译时将其删除)
这里有一个建议的用法(大概是 IdentityT 的起源: http ://www.haskell.org/pipermail/libraries/2007-June/007563.html
主要用途似乎是在源代码级别允许灵活性,例如有人可以将源代码编辑为 xmonad 并替换他们自己的 UserT 而无需编辑太多代码。
我试图看看它如何适用于库 - 你可以使用它来提供一个占位符,用于在堆栈中间插入一个 monad,不过我不确定这是一个很好的案例。这是我人为的例子:
{-# 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]