首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >哈斯克尔类型推断(ReaderT和元组)

哈斯克尔类型推断(ReaderT和元组)
EN

Stack Overflow用户
提问于 2018-08-23 00:34:09
回答 3查看 92关注 0票数 1

探索这个材料:Lens over tea我遇到了一个有趣的(一开始很简单)点:

代码语言:javascript
复制
ex3 :: (a, b) -> (b, a)
ex3 = do
 a <- fst
 b <- snd
 return (b, a)

一切都很好,但是这个函数使用的是哪种类型的monad (因为我们内部有一个do-block )。经过几次尝试,我得出了这样的结论:

代码语言:javascript
复制
ex2 :: ReaderT (a, b) ((,) b) a
ex2 = ReaderT $ do
  a <- fst
  b <- snd 
  return (b, a)

ex3 :: (a, b) -> (b, a)
ex3 = runReaderT ex2

因此,我们有使用内部一元((,) b)的ReaderT。有趣的是,我对此还不够满意,于是决定重写ex2,而不是使用do表示法。这是我得到的:

代码语言:javascript
复制
ex2 :: Monoid b => ReaderT (a, b) ((,) b) a
ex2 = ReaderT $ 
  \pair -> return (fst pair) >>= 
  \a -> return (snd pair) >>= 
  \b -> (b, a) 

或者甚至是:

代码语言:javascript
复制
ex2 :: Monoid b => ReaderT (a, b) ((,) b) a
ex2 = ReaderT $ 
  \pair -> (mempty, fst pair) >>= 
  \a -> (mempty, snd pair) >>= 
  \b -> (b, a) 

这两种变体都要求b具有Monoid类型限制。问题是:我能不能只用(>>=)编写这个函数,而不使用Monoid限制-就像我们用do-notation变体一样?显然,无论是否使用do-notation,我们都会做同样的事情。也许最大的区别是,我们必须在第二个和第二个函数中的每一步构造单子,这就要求我们声明"b“应该是么半群--一些么半群。在第一种情况下,我们只是从一些monad中提取我们的值-而不是构建它们。有没有人能解释一下,我的想法是正确的吗?

谢谢你!!

EN

回答 3

Stack Overflow用户

发布于 2018-08-23 00:50:21

您还没有完全从do表示法到(>>=)调用中去掉这一点。直接转换如下所示:

代码语言:javascript
复制
ex2 :: ReaderT (a, b) ((,) b) a
ex2 = ReaderT $
  fst >>= (\a ->         -- a <- fst
  snd >>= (\b ->         -- b <- snd
  return (b, a)))        -- return (b, a)

此外,您实际上并没有使用(,) b的单一性,即使它适合在这里用于ReaderT的“内部单元格”。

票数 2
EN

Stack Overflow用户

发布于 2018-08-23 00:39:07

代码语言:javascript
复制
ex3 :: (a, b) -> (b, a)

在前缀表示法中表示

代码语言:javascript
复制
ex3 :: (->) (a, b) (b, a)
       -----------m
                   ------t

因此,monad是m = (->) (a, b),它是Reader (直到同构),并使用一对作为其隐式参数/只读状态。

你不需要么半群。简单的阅读器monad就足够了。如果您想使用ReaderT,请使用identity monad作为内部monad。

代码语言:javascript
复制
ex2 :: Monoid b => ReaderT (a, b) Identity (b, a)
ex2 = ReaderT $ 
  \pair -> Identity (fst pair) >>= 
  \a -> Identity (snd pair) >>= 
  \b -> Identity (b, a) 

当然,上面的代码可以简化。

票数 1
EN

Stack Overflow用户

发布于 2018-08-23 03:18:37

所以总结一下:

  1. 类型的monad是(->) r- just function或simple reader;
  2. 如何在不执行do的情况下对初始函数进行去垃圾处理:

ex3‘::(a,b) -> (b,a) ex3’= fst >>= \a ->和>>= \b -> return (b,a)

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

https://stackoverflow.com/questions/51971403

复制
相关文章

相似问题

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