mis*_*tor 104 monads haskell functional-programming monad-transformers applicative
申请人撰写,monad没有.
上述陈述是什么意思?什么时候比其他人更好?
pig*_*ker 111
如果我们比较类型
(<*>) :: Applicative a => a (s -> t) -> a s -> a t
(>>=) :: Monad m => m s -> (s -> m t) -> m t
Run Code Online (Sandbox Code Playgroud)
我们得到了两个概念分开的线索.这(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
Run Code Online (Sandbox Code Playgroud)
它使用某种效果的结果来决定两次计算(例如发射导弹和签署停战协定),而
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
Run Code Online (Sandbox Code Playgroud)
它使用值在两个计算的值ab
之间进行选择,并且已经执行了两个计算,也许是为了悲剧效果.at
af
monadic版本主要依赖于(>>=)
从值中选择计算的额外功能,这可能很重要.然而,支持这种力量使得monad难以构成.如果我们试图建立'双重绑定'
(>>>>==) :: (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 ???
Run Code Online (Sandbox Code Playgroud)
我们到目前为止,但现在我们的层都混乱了.我们有一个n (m (n t))
,所以我们需要摆脱外在的n
.正如Alexandre C所说,如果我们有合适的话,我们就可以做到
swap :: n (m t) -> m (n t)
Run Code Online (Sandbox Code Playgroud)
将n
内部和内部置换join
到另一个n
.
较弱的"双重应用"更容易定义
(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs
Run Code Online (Sandbox Code Playgroud)
因为层之间没有干扰.
相应地,当你真正需要Monad
s 的额外功能时,以及当你可以摆脱Applicative
支持的刚性计算结构时,这是很好的.
顺便说一下,虽然编写monad很困难,但它可能比你需要的更多.类型m (n v)
表示计算与m
效果- ,然后与计算n
效果-到v
-值,其中,所述m
效果-完成之前n
效果-启动(因此为需要swap
).如果你只是想m
用n
-effects 交错-effects ,那么组合可能太多了!
Con*_*nal 72
申请人撰写,monad没有.
Monads 确实组成,但结果可能不是monad.相反,两种应用的组合物必然是一种应用.我怀疑原始陈述的意图是"应用性构成,而monadness不构成." 改写," Applicative
在成分下关闭,而Monad
不是."
Rot*_*sor 38
如果你有applicatives A1
和A2
,那么该类型data A3 a = A3 (A1 (A2 a))
也是应用性(你可以写在一个通用的方法这种情况下).
在另一方面,如果你有单子M1
和M2
那么该类型data M3 a = M3 (M1 (M2 a))
不一定是单子(不存在用于明智的通用实现>>=
或join
该组合物).
一个例子可以是类型[Int -> a]
(在这里我们撰写类型构造[]
与(->) Int
,这两者都是单子).你可以轻松写作
app :: [Int -> (a -> b)] -> [Int -> a] -> [Int -> b]
app f x = (<*>) <$> f <*> x
Run Code Online (Sandbox Code Playgroud)
这可以概括为任何应用:
app :: (Applicative f, Applicative f1) => f (f1 (a -> b)) -> f (f1 a) -> f (f1 b)
Run Code Online (Sandbox Code Playgroud)
但是没有合理的定义
join :: [Int -> [Int -> a]] -> [Int -> a]
Run Code Online (Sandbox Code Playgroud)
Lan*_*dei 17
不幸的是,我们真正的目标,monad的组成,更加困难...事实上,我们实际上可以证明,在某种意义上,没有办法只使用两个monad的操作来构造具有上述类型的连接函数(参见附录中的证明大纲).因此,我们可能希望形成一个组合的唯一方法是,如果有一些额外的结构连接这两个组件.
撰写monad,http: //web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
小智 7
分配法解决方案l:MN - > NM就足够了
保证NM的一致性.要看到这个,你需要一个单元和一个单元.我将专注于mult(单位是unit_N unitM)
NMNM - l -> NNMM - mult_N mult_M -> NM
Run Code Online (Sandbox Code Playgroud)
这并不能保证MN是monad.
然而,当你有分配法律解决方案时,关键的观察就会发挥作用
l1 : ML -> LM
l2 : NL -> LN
l3 : NM -> MN
Run Code Online (Sandbox Code Playgroud)
因此,LM,LN和MN是单子.问题出现在LMN是否是一个monad(或者是
(MN)L - > L(MN)或N(LM) - >(LM)N
我们有足够的结构来制作这些地图.然而,正如Eugenia Cheng所观察到的,我们需要一个六边形条件(相当于Yang-Baxter方程的表示)来保证任一构造的单一性.实际上,在六边形条件下,两个不同的单子重合.