繁体   English   中英

Haskell - 带有两个参数的类型类的翻转参数

[英]Haskell - flip arguments of a typeclass with two parameters

我有一个multiparam类型类,它提供了一个有意义的函数交换参数:

class Swappable a b where
    swappable :: a -> b -> Bool

因此,如果ab形成Swappable ab ,那么ba应该形成Swappable ba 为每个普通实例编写一个交换实例将是一件苦差事,所以我天真地写道

instance Swappable a b => Swappable b a where
    swappable b a = swappable a b

哪个不能编译,出现以下错误:

    • Illegal instance declaration for ‘Swappable b a’
        (All instance types must be of the form (T a1 ... an)
         where a1 ... an are *distinct type variables*,
         and each type variable appears at most once in the instance head.
         Use FlexibleInstances if you want to disable this.)
    • In the instance declaration for ‘Swappable b a’
   |
12 | instance Swappable a b => Swappable b a where
   |                           ^^^^^^^^^^^^^

现在,我并不反对开启FlexibleInstances ,但我不明白为什么我首先需要它。 所有类型变量都出现一次,并且都是不同的。 那么为什么我会收到这个错误?

All instance types must be of the form (T a1 ... an)

表示您的实例必须是表单

instance Swappable (T a1 .. an) (U b1 .. bn) where ...

其中TU是类型构造函数。 没有这个扩展,你不能只有单个变量ab而没有顶部的构造函数。

无论如何, FlexibleInstances是无害的,默认情况下应该可以开启。 也许Haskell报告的未来版本将包含它。

相反,我会更关注重叠。 instance Swappable ba => Swappable ab将与任何其他实例重叠。 它还需要不可判定的实例。 我不确定你想要实现的是一个好主意。

在这种情况下,您可以编写以下内容:

{-# LANGAUGE UndecidableSuperClasses #-} -- 2
class Swappable b a => Swappable a b where -- 1
      swappable :: a -> b -> Bool
      swappable = flip swappable -- 3

(1)如果你知道abSwappable ,那么你也知道baSwappable 那是,

swappable' :: Swappable a b => b -> a -> Bool
swappable' = swappable

编译,即使参数顺序似乎“错误”,因为Swappable ab约束本身意味着Swappable ba ,并且它是swappable调用选择的实现。

(2)使GHC不停抱怨的递归超Swappable 这是GHC 8.0.1中引入的最新功能。 请注意,我们不需要FlexibleInstances (尽管它是无害的)或UndecidableInstances (大部分都是OK)或OverlappingInstances (它设置了klaxons咆哮)。 UndecidableSuperClasses可能介于“危险”等级的前两个之间。

(3)是swappable的默认实现。 无论你喜欢什么,你都可以做到。 该课程的用法如下:

instance Swappable Bool Int where
  swappable _ 0 = False
  swappable True n = n > 0
  swappable False n = n < 0
instance Swappable Int Bool where -- program does not compile if this is missing

instance Eq a => Swappable a a where swappable = (==)

Swappable Int Bool类具有Swappable Bool Int作为超类,因此可以根据该超类定义其swappable类。 Swappable Bool Int包含逻辑。 如果其中一个实例丢失,那么另一个实例的超类约束将无法实现,因此程序将无法编译。 在Swappable Swappable aa案例中,实例是它自己的“superinstance”。 (它确实需要FlexibleInstances ,但原因与我们的目的正交。)

这一切都有效:

> swappable 5 5 -- defaulted to Integer, mind you
True
> swappable True (5 :: Int)
True
> swappable (5 :: Int) False
False
> swappable' (0 :: Int) True
False

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM