【问题标题】:Why can't I define a Haskell Arrow instance in terms of arr and *** / &&&为什么我不能用 arr 和 *** / &&& 定义 Haskell Arrow 实例
【发布时间】:2011-06-02 18:30:43
【问题描述】:

我仍然在掌握如何在 Haskell 中定义和使用箭头。在定义新箭头时,我更容易考虑 *** 或 &&& 而不是第一个和第二个,因为大多数时候我希望对两个箭头组合时进行特殊处理。

但是,Arrow 类不允许根据 arr 和 *** 或 &&& 定义箭头,并且需要包含 first 的定义。这意味着我不得不编写如下代码 -

instance Arrow X where
  arr f = ...
  f (***) g = ...
  first f = f *** arr id

在我看来,在 Control.Arrow 模块中包含“first”的默认定义并没有什么坏处。这将允许我们在定义 first 或 *** 之间进行选择。

第一个默认定义没有包含在 Arrow 类中是否有充分的理由?我能想到的唯一原因是用户可能会忽略 first 和 *** 的定义,然后你会有循环定义,但这是唯一的原因吗?

【问题讨论】:

  • 我怀疑循环定义的可能性是原因,因为这种情况存在于其他类型类中;例如,(==)(/=)Eq

标签: haskell arrows


【解决方案1】:

Data.Monoid 有一个类似的缺失替代最小完整定义:mconcat。与 Arrow 一样,出于性能原因,它缺少这种替代方案。 mappend a b = mconcat[a,b] 效率低,因为 mconcat 中的模式匹配。

使用 Arrows,效率不那么明显但更加残酷:想想无法优化 arr id away:

以CleisliArrow为例,是这样的:

first f (x,y) = do
    x' <- f x
    return (x',y)

它会是:

first f (x,y) = do
    x' <- f x
    y' <- arr id y
    return (x',y')

arr 函数无法与 id 函数进行模式匹配,因此必须引入额外的开销来包装该函数。

【讨论】:

    【解决方案2】:

    我实际上相信是循环性阻止了某人编写默认方法。但正如@camccann 指出的那样,这应该阻止任何人。建议更改!

    【讨论】:

    • 我能想象的唯一另一个原因是,如果意图在某种程度上是模棱两可的,但我认为 first ff *** id 对于表现良好的人来说应该总是等价的实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多