首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应用写作,单子不写

应用写作,单子不写
EN

Stack Overflow用户
提问于 2011-08-12 13:35:41
回答 7查看 14.9K关注 0票数 122

应用写作,单子不写作。

以上的说法是什么意思?什么时候一个比另一个更好?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-08-12 15:44:52

如果我们比较这些类型

代码语言:javascript
复制
(<*>) :: Applicative a => a (s -> t) -> a s -> a t
(>>=) :: Monad m =>       m s -> (s -> m t) -> m t

我们对这两个概念的区别有一个线索。(s -> m t)(>>=)类型中表明,s中的值可以确定m t中计算的行为。Monad允许值和计算层之间的干扰。(<*>)运算符不允许这样的干扰:函数和参数计算不依赖于值。这真的很疼。比较

代码语言:javascript
复制
miffy :: Monad m => m Bool -> m x -> m x -> m x
miffy mb mt mf = do
  b <- mb
  if b then mt else mf

它利用某种效果的结果来决定两种计算(例如发射导弹和签署停战协议)。

代码语言:javascript
复制
iffy :: Applicative a => a Bool -> a x -> a x -> a x
iffy ab at af = pure cond <*> ab <*> at <*> af where
  cond b t f = if b then t else f

它使用ab的值在ataf两种计算值之间进行选择,这两者都实现了,可能会产生悲剧性效果。

一元版本基本上依赖于(>>=)的额外能力来从值中选择计算,这可能很重要。然而,支持这种权力会使单曲很难组成。如果我们试图构建“双绑定”

代码语言:javascript
复制
(>>>>==) :: (Monad m, Monad n) => m (n s) -> (s -> m (n t)) -> m (n t)
mns >>>>== f = mns >>-{-m-} \ ns -> let nmnt = ns >>= (return . f) in ???

我们走到了这一步,但现在我们的图层都乱七八糟了。我们有一个n (m (n t)),所以我们需要去掉外部n。就像亚历山大C说的,如果我们有一个合适的

代码语言:javascript
复制
swap :: n (m t) -> m (n t)

n内部转换为join并将其传递给另一个n

较弱的“双应用”更容易定义。

代码语言:javascript
复制
(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs

因为两层之间没有干扰。

相应地,很好地认识到什么时候真正需要Monad的额外能力,以及什么时候可以摆脱Applicative所支持的刚性计算结构。

请注意,顺便说一句,尽管编写单曲很困难,但它可能超出了您的需要。m (n v)类型表示用m-effects计算,然后用n-effects计算到v-value,m-effects在n-effects启动之前完成(因此需要swap)。如果您只想将m-effects与n-effects交织在一起,那么作文可能要求太多了!

票数 124
EN

Stack Overflow用户

发布于 2011-08-15 20:20:13

应用写作,单子不写作。

单元组确实会作曲,但结果可能不是一个单曲。相反,两个应用程序的组成必然是一个应用程序。我怀疑最初声明的意图是:“实用性是构成的,而君主则不是。”重新措辞,"Applicative在组合下关闭,而Monad不是。“

票数 87
EN

Stack Overflow用户

发布于 2011-08-12 13:48:46

如果您有应用程序A1A2,那么类型data A3 a = A3 (A1 (A2 a))也是可应用的(您可以以通用的方式编写这样的实例)。

另一方面,如果您有monad M1M2,那么类型data M3 a = M3 (M1 (M2 a))不一定是monad(对于组合的>>=join没有合理的通用实现)。

一个例子可以是类型[Int -> a] (在这里,我们使用(->) Int组成一个类型构造器[],这两个构造函数都是monad)。你可以很容易地写

代码语言:javascript
复制
app :: [Int -> (a -> b)] -> [Int -> a] -> [Int -> b]
app f x = (<*>) <$> f <*> x

这可以概括为任何应用程序:

代码语言:javascript
复制
app :: (Applicative f, Applicative f1) => f (f1 (a -> b)) -> f (f1 a) -> f (f1 b)

但没有合理的定义

代码语言:javascript
复制
join :: [Int -> [Int -> a]] -> [Int -> a]

如果您不相信这一点,请考虑下面这个表达式:

代码语言:javascript
复制
join [\x -> replicate x (const ())]

在提供一个整数之前,返回列表的长度必须在石头中设置,但它的正确长度取决于所提供的整数。因此,这种类型不可能存在正确的join函数。

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

https://stackoverflow.com/questions/7040844

复制
相关文章

相似问题

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