gpt4 book ai didi

haskell - 为什么使用 applicative functors 不如 monads 进行整数除法?

转载 作者:行者123 更新时间:2023-12-02 02:21:45 28 4
gpt4 key购买 nike

我正在阅读 Graham Hutton 的 Haskell 编程,对下面概述的思路感到困惑。

他使用下面的示例通过展示应用仿函数在返回类型为 Maybe 的除法运算中的缺点来激发对 monad 的使用。处理指示可能被零除的错误情况。

鉴于:

data Expr = Val Int | Div Expr Expr

safediv :: Int -> Int -> Maybe Int
safediv _ 0 = Nothing
safediv n m = Just (n `div` m)

eval :: Expr -> Maybe Int
eval (Val n) = pure n --type: Just(n)?
eval (Div x y) = pure safediv <*> eval x <*> eval y --type: Maybe(Maybe Int)?

他继续解释:

However, this definition is not type correct. In particular, the function safediv has type Int->Int->Maybe Int, whereas in the above context a function of type Int->Int->Int is required.

Replacing pure safediv by a custom defined function wound not help either, because this function would need to have type Maybe(Int->Int->Int), which does not provide any means to indicate failure when the second integer argument is zero. (X)

The conclusion is that the function eval does not fit the pattern of effectful programming that is captured by applicative functors. The applicative style restricts restricts us to applying pure functions to effectful arguments: eval does not fit this pattern because the function safediv that is used to process the resulting values is not a pure function, but may itself fail.



我不是 Haskell 程序员,而是来自 eval (Div x y) 的类型。似乎是 Maybe(Maybe Int) - 可以简单地压扁,不是吗? (类似于 Scala 中的 flatten 或 Haskell 中的 join)。这里真正的问题是什么?

不管是否 x,yJust(s)/Nothing(s)看来 safediv将正确评估 - 这里唯一的问题是可以适当转换的返回类型。作者究竟是如何从他的论点得出这个结论的,这是我很难理解的。

...applicative style restricts restricts us to applying pure functions to effectful arguments



另外,为什么段落标记为 (X)当问题似乎是或返回类型未对齐时,上面提出了该声明。

我知道应用程序可用于更有效地链接计算,其中一个的结果不会影响另一个 - 但在这种情况下,我对失败的发生方式/位置以及是否只是一个简单的返回类型修复会感到困惑解决这个问题:
eval (Div x y) = join(pure safediv <*> eval x <*> eval y)
safediv一定要纯洁吗? AFAIK 它也可以是 F[Maybe] 类型或 F[Either] , 不?我可能会错过什么?我可以看到他要去哪里,但不确定这是否是到达那里的正确例子,恕我直言。

最佳答案

I'm not a Haskell programmer but from the type of eval (Div x y) it seems be that of Maybe(Maybe Int) - which can simply be squashed, no? (Something like a flatten in Scala or join in Haskell). What really is the issue here? … the only issue here is the return type which can be transformed appropriately



这是关键问题! “Squashing”本质上是一个单子(monad)操作——事实上, join 的类型签名是 join :: Monad m => m (m a) -> m a .如果您将自己限制在应用方法 pure(<*>) ,没有办法实现,但是如果你让自己使用 (>>=)就变得容易了也是。当然,您可以轻松实现 flattenMaybe :: Maybe (Maybe a)) -> Maybe a不使用单子(monad),但这违背了 Applicative 等概念的目的和 Monad ,应该适用于广泛的类型,而不仅仅是 Maybe .

Irrespective of whether x,y are Just(s)/Nothing(s) it seems safediv will correctly evaluate - the only issue here is the return type which can be transformed appropriately. How exactly does the author go from his argument to this conclusion is what I'm having a hard time understanding.

...applicative style restricts restricts us to applying pure functions to effectful arguments



另外,为什么段落标记为 (X)上面提出的要求,当
问题似乎是或返回类型未对齐。

这里的想法是这样的。假设您有两个函数和两个值:

nonEffectful :: a -> b -> c
effectful :: a -> b -> m c

effectfulA :: m a
effectfulB :: m b

现在,如果您想申请 nonEffectful两个有效参数的函数, m只需 Applicative : 很容易做到 nonEffectful <$> effectfulA <*> effectfulB :: m c .但是,如果您尝试使用 effectful相反,您遇到了一个问题:返回类型为 m (m c)而不是 m c .到“ Squash ” m (m c)进入 m c , 你需要一个 Monad实例。所以应用程序只能将纯(非有效)函数应用于有效参数,但 monad 让我们将有效函数应用于有效参数。这就是 Hutton 试图做的,但有一个特定的功能 safeDiv :: Int -> Int -> Maybe Int .

(我在上面的讨论中没有提到的一件事是直觉:为什么在直觉而不是形式层面上,特定计算需要 monad?正如您已经注意到的,答案与依赖性有关。对于 nonEffectful <$> effectfulA <*> effectfulB ,两个有效值相互没有影响。但是,有了 effectful <$> effectfulA <*> effectfulB ,突然之间就有了依赖关系: effectful 函数必须依赖于传递给它的有效计算的结果。可以想到 Monad表示可以相互依赖的有效计算的概念,而 Applicative 表示不能相互依赖的有效计算的概念(尽管纯函数可能依赖于它们)。类似地,为了评估嵌套计算 m (m a),你首先需要评估外部计算,然后评估生成的内部有效计算。同样,我们有一个有效计算,它依赖于另一个有效计算,所以这重新询问 Monad .)

关于haskell - 为什么使用 applicative functors 不如 monads 进行整数除法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60518561/

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