Monad 不组合,对吧?
Monads do not compose, right?
当我在研究一个演讲时,我遇到了一些我认为不可能的事情,我仍然无法弄清楚它为什么有效。在Control.Bind
模块中,有fish算子的定义:
composeKleisli ∷ ∀ a b c m. Bind m ⇒ (a → m b) → (b → m c) → a → m c
上面的文档给出了一个例子:
third = tail >=> tail >=> head
这是我脑子里没有计算的地方。我以为它永远不会编译*,但它确实可以:
> :t tail >=> tail >=> head
forall t2. Array t2 -> Maybe t2
怎么会这样?显然 tail
和 head
的输出不同 m
.
* 或者类型检查器会推断出以下类型:forall t2. Array (Array t2) -> Array t2
所以,m
在那种情况下是 Maybe
,因此你不需要组合不同类型的 monad。
更具体地说:
tail :: forall a. Array a -> Maybe (Array a)
head :: forall a. Array a -> Maybe a
所以
composeKliesli tail tail :: forall a. Array a → Maybe (Array a)
composeKliesli (composeKliesli tail tail) head :: forall a. Array a -> Maybe a
要看到您需要将 m
替换为 Maybe
和 a
,将 b
和 c
替换为 a
或Array a
类型为 composeKliesli
.
当我在研究一个演讲时,我遇到了一些我认为不可能的事情,我仍然无法弄清楚它为什么有效。在Control.Bind
模块中,有fish算子的定义:
composeKleisli ∷ ∀ a b c m. Bind m ⇒ (a → m b) → (b → m c) → a → m c
上面的文档给出了一个例子:
third = tail >=> tail >=> head
这是我脑子里没有计算的地方。我以为它永远不会编译*,但它确实可以:
> :t tail >=> tail >=> head
forall t2. Array t2 -> Maybe t2
怎么会这样?显然 tail
和 head
的输出不同 m
.
* 或者类型检查器会推断出以下类型:forall t2. Array (Array t2) -> Array t2
所以,m
在那种情况下是 Maybe
,因此你不需要组合不同类型的 monad。
更具体地说:
tail :: forall a. Array a -> Maybe (Array a)
head :: forall a. Array a -> Maybe a
所以
composeKliesli tail tail :: forall a. Array a → Maybe (Array a)
composeKliesli (composeKliesli tail tail) head :: forall a. Array a -> Maybe a
要看到您需要将 m
替换为 Maybe
和 a
,将 b
和 c
替换为 a
或Array a
类型为 composeKliesli
.