应用写作,单子不写作。
以上的说法是什么意思?什么时候一个比另一个更好?
发布于 2011-08-12 15:44:52
如果我们比较这些类型
(<*>) :: 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允许值和计算层之间的干扰。(<*>)运算符不允许这样的干扰:函数和参数计算不依赖于值。这真的很疼。比较
miffy :: Monad m => m Bool -> m x -> m x -> m x
miffy mb mt mf = do
b <- mb
if b then mt else mf它利用某种效果的结果来决定两种计算(例如发射导弹和签署停战协议)。
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的值在at和af两种计算值之间进行选择,这两者都实现了,可能会产生悲剧性效果。
一元版本基本上依赖于(>>=)的额外能力来从值中选择计算,这可能很重要。然而,支持这种权力会使单曲很难组成。如果我们试图构建“双绑定”
(>>>>==) :: (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说的,如果我们有一个合适的
swap :: n (m t) -> m (n t)将n内部转换为join并将其传递给另一个n。
较弱的“双应用”更容易定义。
(<<**>>) :: (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交织在一起,那么作文可能要求太多了!
发布于 2011-08-15 20:20:13
应用写作,单子不写作。
单元组确实会作曲,但结果可能不是一个单曲。相反,两个应用程序的组成必然是一个应用程序。我怀疑最初声明的意图是:“实用性是构成的,而君主则不是。”重新措辞,"Applicative在组合下关闭,而Monad不是。“
发布于 2011-08-12 13:48:46
如果您有应用程序A1和A2,那么类型data A3 a = A3 (A1 (A2 a))也是可应用的(您可以以通用的方式编写这样的实例)。
另一方面,如果您有monad M1和M2,那么类型data M3 a = M3 (M1 (M2 a))不一定是monad(对于组合的>>=或join没有合理的通用实现)。
一个例子可以是类型[Int -> a] (在这里,我们使用(->) Int组成一个类型构造器[],这两个构造函数都是monad)。你可以很容易地写
app :: [Int -> (a -> b)] -> [Int -> a] -> [Int -> b]
app f x = (<*>) <$> f <*> x这可以概括为任何应用程序:
app :: (Applicative f, Applicative f1) => f (f1 (a -> b)) -> f (f1 a) -> f (f1 b)但没有合理的定义
join :: [Int -> [Int -> a]] -> [Int -> a]如果您不相信这一点,请考虑下面这个表达式:
join [\x -> replicate x (const ())]在提供一个整数之前,返回列表的长度必须在石头中设置,但它的正确长度取决于所提供的整数。因此,这种类型不可能存在正确的join函数。
https://stackoverflow.com/questions/7040844
复制相似问题