gpt4 book ai didi

haskell - Arrow 和 Monad,两个独立的观点来组成计算?

转载 作者:行者123 更新时间:2023-12-03 14:16:09 26 4
gpt4 key购买 nike

我在 Monad.Reader#13 中阅读了 Brent Yorgey 的“The Typeclassopedia”。 ,并发现“Functor hierachy”与“Category hierachy”相互依赖,如图1所示。
Figure.1

据作者说,ArrowApply == Monad ,特别是前面的只是一个类型类实例,可以在什么时候使用

"we would like to be able to compute an arrow from intermediate results, and use this computed arrow to continue the computation. This is the power given to us by ArrowApply."



但是我们怎样才能把这些东西放在一起呢?我的意思是在 Monad 和 Arrow 中都有一些流控制功能(例如 ifelseArrowChoiceforMArrowLoop ),并且某些功能在 Monad 中似乎“缺失” ( (***)(|||)first)。所有这些似乎我们需要在使用 Monad 或 Arrow 系统来构建我们的副作用计算流程之间做出选择,并且会在另一个系统中丢失一些特性。

最佳答案

答案就在下面(所有这些都来自 Control.Arrow docs )

newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
instance Monad ArrowApply a => Monad (ArrowMonad a)
ArrowMonad newtype 是我们定义 Monad 的车辆。 ArrowApply 的实例箭头。我们本可以使用
instance Monad ArrowApply a => Monad (a ())

但这会导致 Haskell 的有限类型类推断出现问题(我理解它可以与 UndecideableInstances 扩展一起使用)。

你可以想到 Monad ArrowApply 的实例箭头将一元操作转换为等效的箭头操作,如源代码所示:
instance ArrowApply a => Monad (ArrowMonad a) where
return x = ArrowMonad (arr (\_ -> x))
ArrowMonad m >>= f = ArrowMonad (m >>>
arr (\x -> let ArrowMonad h = f x in (h, ())) >>>
app)

所以知道我们知道 ArrowApplyMonad 一样强大因为我们可以实现所有 Monad里面的操作。令人惊讶的是,反过来也是如此。这是由 Kleisli 给出的。 @hammar 指出的新类型。观察:
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }

instance Monad m => Category (Kleisli m) where
id = Kleisli return
(Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)

instance Monad m => Arrow (Kleisli m) where
arr f = Kleisli (return . f)
first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))

instance Monad m => ArrowApply (Kleisli m) where
app = Kleisli (\(Kleisli f, x) -> f x)

instance Monad m => ArrowChoice (Kleisli m) where
left f = f +++ arr id
right f = arr id +++ f
f +++ g = (f >>> arr Left) ||| (g >>> arr Right)
Kleisli f ||| Kleisli g = Kleisli (either f g)

前面给出了使用 monad 操作的所有常用箭头操作的实现。 (***)未提及,因为它有一个默认实现,使用 firstsecond :
f *** g = first f >>> second g

所以现在我们知道如何使用 Monad 操作来实现箭头( ArrowArrowChoiceArrowApply )操作。

回答您关于为什么我们同时拥有 Monad 的问题和 Arrow如果他们证明是等价的:

当我们不需要 monad 的全部功能时,功能较弱的箭头很有用,就像应用仿函数很有用一样。即使 ArrowApplyMonad是等价的, ArrowArrowChoice没有 appMonad 中无法表示的东西等级制度。反之亦然, Applicative在箭头层次结构中不可表示。
这是因为 ap在单子(monad)层次结构中出现“第一”,在箭头层次结构中出现“最后”。

monad 和箭头世界之间的主要语义差异是箭头捕获转换( arr b c 意味着我们从 c 生成 b),而 monad 捕获操作( monad a 生成 a)。 Kleisli 中很好地反射(reflect)了这种差异。和 ArrowMonad新类型:
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)

Kleisli我们必须添加源类型 a ,并在 ArrowMonad我们将其设置为 () .

我希望这能让你满意!

关于haskell - Arrow 和 Monad,两个独立的观点来组成计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8365992/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com