繁体   English   中英

非单子函数的绑定运算符

[英]Bind operator for non-monadic functions

我或多或少地把头绕在单子上,但我无法推断出表达方式

(>>=) id (+) 3

计算结果为 6。似乎表达式以某种方式简化为

(+) 3 3

但如何? 3如何应用两次? 有人可以解释幕后发生的事情吗?

这遵循如何为((->) r)类型定义>>=

(f =<< g) x  =  f (g x) x

因此

(>>=) id (+) 3
=
(id >>= (+)) 3
=
((+) =<< id) 3
=
(+) (id 3) 3
=
3 + 3

查看类型:

> :t let (f =<< g) x = f (g x) x in (=<<)
let (f =<< g) x = f (g x) x in (=<<)
        :: (t1 -> (t2 -> t)) -> (t2 -> t1) -> (t2 -> t)

> :t (=<<)
(=<<) :: Monad m => (a -> m b) -> m a -> m b

类型匹配

t1 ~ a
(t2 ->) ~ m    -- this is actually ((->) t2)`
t ~ b

因此,这里的约束Monad m表示Monad ((->) t2) ,它定义了=<<>>=的定义,它们会被使用。

如果你想从类型推导出定义,

(>>=) :: Monad m => m a -> (a -> m b) -> m b
m ~ ((->) r)

(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
(>>=)    f            g                r =  b
  where
  a  = f r
  rb = g a
  b  = rb r

简化后成为我们上面使用的那个。

如果你想“用文字”来理解它,

(=<<) :: (Monad m, m ~ ((->) r)) => (a -> m b) -> m a -> m b
(f =<< g) x  =  f (g x) x
  • g是“可以计算”“ a ”的“一元值”,表示为r -> a
  • fa计算“可以计算”a“ b ”的“一元值”,表示为r -> b
  • 因此\x -> f (gx) x是一个“可以计算”a“ b ”的一元值,给定一个“ r ”。

所以这些“非单子函数”实际上是单子值,它们恰好是函数。

因此,在您的示例中, g = idf = (+)

  • id是一个“一元值”,“可以计算”一个“ a ”,一个a -> a
  • (+) a计算一个“可以计算” a“ b ”的“一元值”,一个a -> b ,其中b实际上也是一个a
  • 因此\x -> (+) (id x) x是一个“可以计算”一个“ a ”的一元值,给定一个“ a ”:
(>>=) id (+)
=
((+) =<< id) 
=
\x -> (+) (id x) x
=
\x -> (+)     x  x

为威尔的出色回答增添了一些色彩。

如果我们查看source ,我们有这个:

 instance Monad ((->) r) where f >>= k = \ r -> k (fr) r

如果我们稍微重新排列输入表达式,我们会得到(id >>= (+)) 3 这现在类似于上面显示的形式。 现在将输入拟合到上述“模板”中,我们可以将输入重写为\ r -> (+) (id r) r

这与我们为最终评估得出的表达式相同,即(+) (id 3) 3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM