非单子函数的绑定运算符
Bind operator for non-monadic functions
我或多或少对 monad 很感兴趣,但我无法推断出如何表达
(>>=) 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
f a
计算一个“可以计算”一个“b
”的“单子值”,表示为r -> b
,
- 因此
\x -> f (g x) x
是一个单子值,“可以 计算”一个“b
”,给定一个“r
”。
所以这些“非单子函数”实际上是单子值,恰好是函数。
因此在您的示例中,g = id
、f = (+)
和
id
是一个“单子值”,它“可以 计算”一个“a
”,一个a -> a
(+) a
计算“可以计算”一个“b
”,一个a -> b
,b
实际上也是一个 a
,
- 因此
\x -> (+) (id x) x
是一个单子值,“可以 计算”一个“a
”,给定一个“a
”:
(>>=) id (+)
=
((+) =<< id)
=
\x -> (+) (id x) x
=
\x -> (+) x x
为 Will 的出色回答增添色彩。
如果我们查看 source,我们有:
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
如果我们稍微重新排列输入表达式,我们会得到 (id >>= (+)) 3
。这现在类似于上面显示的表单。现在将输入拟合到上面的'template',我们可以将输入重写为\ r -> (+) (id r) r
这与我们为最终评估得出的表达式相同,即 (+) (id 3) 3
我或多或少对 monad 很感兴趣,但我无法推断出如何表达
(>>=) 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
f a
计算一个“可以计算”一个“b
”的“单子值”,表示为r -> b
,- 因此
\x -> f (g x) x
是一个单子值,“可以 计算”一个“b
”,给定一个“r
”。
所以这些“非单子函数”实际上是单子值,恰好是函数。
因此在您的示例中,g = id
、f = (+)
和
id
是一个“单子值”,它“可以 计算”一个“a
”,一个a -> a
(+) a
计算“可以计算”一个“b
”,一个a -> b
,b
实际上也是一个a
,- 因此
\x -> (+) (id x) x
是一个单子值,“可以 计算”一个“a
”,给定一个“a
”:
(>>=) id (+)
=
((+) =<< id)
=
\x -> (+) (id x) x
=
\x -> (+) x x
为 Will 的出色回答增添色彩。
如果我们查看 source,我们有:
instance Monad ((->) r) where f >>= k = \ r -> k (f r) r
如果我们稍微重新排列输入表达式,我们会得到 (id >>= (+)) 3
。这现在类似于上面显示的表单。现在将输入拟合到上面的'template',我们可以将输入重写为\ r -> (+) (id r) r
这与我们为最终评估得出的表达式相同,即 (+) (id 3) 3