在查看变形金刚包时,我发现这个名为IdentityT的monad变换器。
虽然我理解如何使用Identity monad(例如State
只是StateT Identity
的别名)以及monad变换器如何工作,我不知道它与{{1}的关系}。
由于它不在MTL中,我猜它是为了完整而添加在那里并没有实际用途。这是对的吗?
答案 0 :(得分:6)
链接文档确实说
这对由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
的行为相同,唯一的区别是存在一个额外的新类型(当然,在编译时删除)
答案 1 :(得分:2)
这里有一个建议的用法(大概是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]