有没有办法将这两个不连贯的实例中的一个设置为首选? [英] Is there a way to set one of these two incoherent instances as preferred?

查看:73
本文介绍了有没有办法将这两个不连贯的实例中的一个设置为首选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 class

  class C ab其中
f: :b - > a - > b

除此之外,我还共存了两个实例



第一个实例通过逐个应用可折叠集合中的元素来工作:

 实例(可折叠m,C ab)=> C(ma)b其中
f = foldl f

第二个连接两个半群的元素:

  instance(Monoid a)=> C aa其中
f = mappend

当然,一个类型可以是 Monoid Foldable (例如 String )。



由于我假设 mappend 要针对案例进行优化(即,要定义一种联合手头可折叠集合的方式比传输元素更有效),我希望编译器尽可能选择第二个实例。如何表示或执行这种偏好?



确实,为了编译代码,我必须将这些实例指定为 incoherent C aa 更具体,因为它只涉及一种变量类型。






您可以查看GitHub上的代码: kindaro / overlap

解决方案

正如其他人所说,这是一个糟糕的主意。然而,我认为没有 IncoherentInstances 可能是可能的,只要你不需要其他实例。

  instance { - #OVERLAPPABLE# - } 
(可折叠m,C ab,q〜ma)
=> C q b其中
f = foldl f

实例{ - #OVERLAPPING# - }
Monoid a => C aa其中
f = mappend

为了更具可预测性的行为,您甚至可以重新使用它来使用一个类型家庭而不是重叠的实例,但它仍然是一个可怕的想法。这个类没有任何意义。

  * Class Data.Monoid> f(12 :: Sum Int)(ZipList [1,2,3 :: Sum Int])
Sum {getSum = 18}

* Class Data.Monoid> f [1,2,3 :: Int] [12 :: Int]
[1,2,3,12]


I have this class at hand:

class C a b where
    f :: b -> a -> b

Along with it, I have coexist two instances.

The first instance works by applying elements from a foldable collection one by one:

instance (Foldable m, C a b) => C (m a) b where
    f = foldl f

The second conjoins two elements of a semigroup:

instance (Monoid a) => C a a where
    f = mappend

Of course, a type can be an instance of both Monoid and Foldable (example be String).

Since I presume mappend to be optimized for the case (i.e. there to be defined a way of conjoining the foldable collections at hand more efficient than transferring elements one by one), I want the compiler to pick the second instance whenever possible. How can I denote or enforce such preferrence?

Indeed, to have the code compile I have to specify these instances as incoherent which is right away false. As I see it, C a a is more specific since it only involves one variable type.


You can review the code on GitHub: kindaro/overlap.

解决方案

As others have said, this is a terrible idea. However, I think it's probably possible without IncoherentInstances, as long as you don't want any other instances.

instance {-# OVERLAPPABLE #-}
     (Foldable m, C a b, q ~ m a)
   => C q b where
  f = foldl f

instance {-# OVERLAPPING #-}
         Monoid a => C a a where
  f = mappend

For more predictable behavior, you could even recast this to use a type family instead of overlapping instances, but it would still be a terrible idea. This class just doesn't make any sense.

*Class Data.Monoid> f (12 :: Sum Int) (ZipList [1,2,3 :: Sum Int])
Sum {getSum = 18}

*Class Data.Monoid> f [1,2,3:: Int] [12::Int]
[1,2,3,12]

这篇关于有没有办法将这两个不连贯的实例中的一个设置为首选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆