方法重载有多少dictionaries/parameters?

How many dictionaries/parameters for method overloadings?

我可以把约束超级class;我可以在 class; 中对特定方法施加限制;我可以对 class 的实例施加额外的约束。约束以字典传递的形式实现。这是否意味着方法的不同重载会得到不同数量的字典参数?考虑:

class Bar1 a                    -- just some classes
class Bar2 a
class Bar3 a
class Bar4 a
class Bar5 a

class (Bar1 a, Bar2 a) => Foo a  where
  foo :: Bar3 b => a -> b -> Bool             -- `b` is not in class head

instance (Bar1 (Maybe a), Bar2 (Maybe a),     -- needed from superclass
                                              -- ?but (Bar3 b) not needed (nor could it be expressed)
          Bar4 (Maybe a), Bar5 a)             -- additional instance-specific, Bar5 is for part of instance head
         => Foo (Maybe a)  where
  foo x y = True

据我从 了解到,Bar 没有方法并不重要。

因此 Foo 的不同实例可能具有不同的特定于实例的约束,一些可能针对整个实例头,一些可能仅针对一部分——例如 Maybe a 中的 Bar5 a。这是否意味着专门用于 (Maybe a) 的函数 foo 需要传递不同数量的字典,而不是说 Int?这是如何组织的?

询问的原因是 this thread,其中 SPJ 谈到“bindSet 需要两个 Ord 参数 运行-时间,而普通的 bind 没有”。(是的,很正确,但是 bindSet 不是 class 的方法。)我想知道是否已经有一个方法的实例采用不同数量的字典参数的机制?

Superclasses 被编译为 class 字典中的附加字段,因此 class 定义:

class (Bar1 a, Bar2 a) => Foo a  where
  foo :: Bar3 b => a -> b -> Bool

编译为具有三个字段的显式字典数据类型 Foo 的粗略等效项:

{-# LANGUAGE RankNTypes #-}
data Foo a = C:Foo { $p1Foo :: Bar1 a
                   , $p2Foo :: Bar2 a
                   , foo :: forall b. Bar3 b -> a -> b -> Bool }

注意该类型中的foo字段访问器,也作为fooclass方法函数,最终具有多态类型:

foo :: Foo a -> Bar3 b -> a -> b -> Bool

意味着它接受四个参数:一个Foo a字典(包含两个超级class字典Bar1 aBar2 a的字段); Bar3 b 字典作为单独的参数;然后是 ab 参数,然后产生 Bool.

定义带约束的多态实例时:

instance (Bar1 (Maybe a), Bar2 (Maybe a),
          Bar4 (Maybe a), Bar5 a)
         => Foo (Maybe a)  where
  foo x y = True

这定义了一个“字典函数”,用于构建 Maybes 的字典。

$fFooMaybe :: Bar1 (Maybe a) -> Bar2 (Maybe a) 
    -> Bar 4 (Maybe a) -> Bar5 a -> Foo (Maybe a)
$fFooMaybe $dBar1 $dBar2 $dBar4 $dBar5 = C:Foo $dBar1 $dBar2 (\_ _ _ -> True)

请注意 foo 本身仍然始终采用四个参数,但是 C:Foo 字典中具体 Maybe X 类型的字段将在字典 $dBar1 上关闭、$dBar2$dBar4$dBar5 在通过 $fFooMaybe 调用创建 Foo 词典时提供。

太棒了....

  • super classes (Bar1 and Bar2) 是字典中的额外字段
  • 方法函数 (foo) 是 class 函数值字段字典的字段访问器
  • 如果 class 声明中的函数有额外的 class 约束 (Bar3),这些将反映为字段的函数值的额外参数
  • 多态实例(instance Foo (Maybe a))作为字典工厂实现,实例声明中的任何约束(Bar1Bar2Bar4Bar5) 在创建字典时关闭,它可以复制超 classes 并使用任何其他可用的范围内约束来构造方法
  • 的必要函数值

方法 foo 总是采用相同数量的参数,尽管它采用的字典参数数量与没有额外约束的 bar :: a -> Double 方法不同。当以不同类型实例化时,在为该类型创建字典时通过闭包处理额外的约束字典。

这样说清楚了吗?

请注意 ghc -ddump-simpl 有或没有 -dsuppress-all 对于弄清楚它是如何工作的非常有帮助。