首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单片变压器的解剖

单片变压器的解剖
EN

Stack Overflow用户
提问于 2012-11-28 16:19:55
回答 1查看 598关注 0票数 10

我试着学习单台变压器,基于标准的Haskell库(mtl?变形金刚?不知道我下载的Haskell平台-7.4.1附带的是哪一个)。

我认为我注意到的是每个单台转换器定义的公共结构:

  1. 基本类型(“基本”)
代码语言:javascript
复制
- Monad instance

  1. 变压器类型(“BaseT”)
代码语言:javascript
复制
- Monad instance
- MonadTrans instance
- MonadIO instance

  1. 变压器类(“MonadBase”)
代码语言:javascript
复制
- some operations
- instances for other 'BaseT's

例如,对于Writer monad,应该有:

  • 带有Monad实例的Writer数据类型/newtype/type
  • 带有Monad、MonadTrans和MonadIO实例的MonadTrans数据类型/新类型/类型
  • 一个MonadWriter类,以及这个类的实例,用于StateT,ReaderT,IdentityT,.

这就是单台变压器的组织方式吗?我遗漏了什么吗?我有什么不正确的细节吗?

这个问题的动机是找出:

  1. “BaseT”和相应的“MonadBase”和“Base”之间的关系和区别是什么?
  2. 是否需要全部三个
  3. MonadTrans是如何联系的以及它的目的是什么
EN

回答 1

Stack Overflow用户

发布于 2012-11-28 17:40:12

mtl包不实现单台变压器。至少WriterT只是来自transformers再出口

transformers包实现了WriterT,它本身就是一个单台转换器。Writer只是一个别名:

代码语言:javascript
复制
type Writer w = WriterT w Identity

有些库可以单独实现Writer,但无论如何,这只是WriterT的一个特例。(Identity是一个微不足道的单子,它没有任何附加的行为。)

MonadTrans允许您将底层单块封装到转换后的单块中。您可以不使用它,但您需要执行手动包装(例如,请参阅MonadTrans实例定义中的WriterT )。唯一真正需要MonadTrans的用例--当您不知道实际类型的转换器时。

MonadWriter是在mtl中声明的类型类。它的方法(writerpasstelllisten)与WriterT的函数相同。它允许(自动!) WriterT计算通过变压器堆栈,即使你不知道确切的类型(和偶数!)堆里的变压器。

因此,WriterT是唯一“必需”的类型。

对于其他单台变压器来说是一样的:BaseT是变压器,Base是没有底层monad的monad,而MonadBase是所有monad的类型类,在变压器堆栈中的某个位置有BaseT

添加:

你可以在RWH书中找到很好的解释

下面是一个基本的例子:

代码语言:javascript
复制
import Control.Monad.Trans
import Control.Monad.Trans.Writer
import Control.Monad.Trans.Reader hiding (ask)

-- `ask` from transformers
-- ask :: Monad m => ReaderT r m r
import qualified Control.Monad.Trans.Reader as TransReader (ask)

-- `ask` from mtl
-- ask :: MonadReader r m => m r
import qualified Control.Monad.Reader as MtlReader (ask)

-- Our monad transformer stack:
-- It supports reading Int and writing String
type M m a = WriterT String (ReaderT Int m) a

-- Run our monad
runM :: Monad m => Int -> M m a -> m (a, String)
runM i action = runReaderT (runWriterT action) i

test :: Monad m => M m Int
test = do
  tell "hello"
  -- v <- TransReader.ask     -- (I) will not compile
  v1 <- lift TransReader.ask  -- (II) ok
  v2 <- MtlReader.ask         -- (III) ok
  return (v1 + v2)

main :: IO ()
main = runM 123 test >>= print

注意,编译器将拒绝(I) (尝试查看错误消息!)。但是(II)会编译,这要归功于MonadTrans (“显式提升”)。多亏了MonadReader(III)才能开箱即用(“隐式提升”)。请阅读RWH书籍,以了解它的工作原理。

(在示例中,我们从两个不同的模块导入ask,这就是我们需要合格导入的原因。通常一次只使用其中一种。)

而且,我也不是有意专门询问Writer的。

我不太明白..。ReaderState和其他人使用相同的架构。将Writer替换为State,您将得到对State的解释。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13609626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档