为什么我不能用arr和***/&&&来定义Haskell Arrow实例

Anu*_*ain 12 haskell arrows

我仍然在Haskell中定义和使用Arrows.在定义新箭头的同时,我更容易用***或&&&而不是第一和第二来思考,因为大多数时候我想要在两个箭头组合时进行特殊处理.

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

instance Arrow X where
  arr f = ...
  f (***) g = ...
  first f = f *** arr id
Run Code Online (Sandbox Code Playgroud)

在我看来,在Control.Arrow模块中包含'first'的默认定义也没有任何害处.这将允许我们在定义第一个或***之间做出选择.

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

com*_*nad 5

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

有了箭头,低效率就不那么明显了,但更加残酷:想想无法优化arr id:

使用CleisliArrow作为示例Arrow,它是这样的:

first f (x,y) = do
    x' <- f x
    return (x',y)
Run Code Online (Sandbox Code Playgroud)

它将是:

first f (x,y) = do
    x' <- f x
    y' <- arr id y
    return (x',y')
Run Code Online (Sandbox Code Playgroud)

arr函数不能与id函数进行模式匹配,因此需要引入额外的开销来包装该函数.


aug*_*tss 4

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