哪些语言扩展可以编写 "class A (B c) => D c where ..." ?这种类型 class 声明的含义是什么?

Which language extensions enable to write "class A (B c) => D c where ..." ? What is the meaning of this type class declaration?

我试图理解以下 class 声明:

class (MonadHold t (PushM t), MonadSample t (PullM t), Functor (Event t), Functor (Behavior t)) => Reflex t where
  data Behavior t :: * -> *

Reflex FRP 库中。

1 ) 哪些语言扩展使得编写 Functor (Behavior t) => Reflex t 成为可能?我想这是语言扩展的组合。我猜涉及类型家族,但还有什么?

换句话说,我必须打开什么语言扩展才能编译包含 class A (B c) => D c where ... 的代码?

2) class A (B c) => D c where ... 是什么意思?

3 ) 你能举一个超级简单的例子来解释为什么以及什么时候想要写 class A (B c) => D c where ... 吗?

4) 哪里描述了class A (B c) => D c where ... 的意思?我想有一篇 SPJ 论文或演讲描述了它,请指点一下好吗?

编辑:

更多相关信息:

Here 写成:

In Haskell 98 the context of a class declaration (which introduces superclasses) must be simple; that is, each predicate must consist of a class applied to type variables.

如果我正确地解释了上面的引文,那么在 Haskell98 中只允许 class A b=>C b where 形 class 声明,这意味着 class A(B c) => D c 是不允许的。所以问题是,如果允许后者,而不允许前者,那么谁以及什么定义了后者的含义?后者是不正确的 Haskell 98 语法所以它的意思在任何 Haskell 98 书中也没有描述,那么后者的意义在哪里 described/documented/specified?

首先,正如您猜对的那样,Behaviour 是一个 associated data type,因此属于 TypeFamilies 扩展。

class Functor (Behaviour t) => Reflex t where data Behaviour t :: * -> * 的要点是强制要求对于作为 Reflex 的实例的任何类型 t,无论您定义什么数据类型作为关联数据类型 Behaviour t,你还必须使该类型成为 Functor.

的实例

这是一个小例子:假设我这个 class 定义:

{-# LANGUAGE TypeFamilies, FlexibleContexts #-}

class Functor (F a) => Funky a where
    data F a :: * -> *

这允许写类似

的东西
frobulate :: (Funky a) => F a Int -> F a Bool
frobulate = fmap (< 5)

因为 frobulate 可以根据 Funky a 自由假设 Functor (F a).

以下内容本身被类型检查器拒绝:

instance Funky Int where
    data F Int a = MkF a

因为关联的数据类型 F Int 不是 Functor 的实例:

No instance for (Functor (F Int))
  arising from the superclasses of an instance declaration
In the instance declaration for `Funky Int'

这迫使您还添加一个实例定义,例如

instance Functor (F Int) where
    fmap f (MkF x) = MkF (f x)

请注意,后一个 Functor 实例也需要 FlexibleInstances 开启。

以下是我对答案的理解。理解了一段时间,所以记录下来,也许对其他人有帮助。

传统类型 class 声明 (Haskell 98) class (Eq a) => MyClass a where 表示 如果 aMyClassa 必须是 Eq 的实例,左侧 Eq a (意味着 aEq 的实例)是谓词如果右侧为真 MyClass a(意味着 aMyClass 的实例),则必须为真。

所以换句话说,class 声明就像 class ($Predicate) => MyClass classInstance,其中 $Predicate 可以是例如 Eq a,这意味着 a 是一个实例Eq

但如果启用 FlexibleContexts 语言扩展,则谓词可能比 ATypeClass typeParameter.

更复杂

它可以是 ATypeClass SomeComplexType 这意味着 - 通过 概括 Haskell 98 的规则 SomeComplexType 是 [=34 的一个实例=].

Haskell 报告中隐含地描述了这个概括过程(如 Daniel 的回答中所述)。

下面三个小程序演示了这个泛化规则。第一个不编译第二个,第三个再次编译。

第二个编译失败,因为 Smells 不是 StringLike,正如 IntLike 的 class 声明所要求的那样。但是,如果我们删除该约束(在第三个程序中),程序将再次编译。

这是一个编译的玩具示例:

{-# LANGUAGE FlexibleContexts #-}


class StringLike a where
 getString :: a->String

class (StringLike Smells) =>IntLike a where
 getInt :: a-> Int

instance IntLike Colors where
  getInt x = 0

instance StringLike Colors where
 getString x = "Hello"

instance StringLike Smells where
 getString x = "Bad"

data Colors = Blue | Red
data Smells = Rose | Trash

然而以下失败:

{-# LANGUAGE FlexibleContexts #-}


class StringLike a where
 getString :: a->String

class (StringLike Smells) =>IntLike a where
 getInt :: a-> Int

instance IntLike Colors where
  getInt x = 0

instance StringLike Colors where
 getString x = "Hello"


data Colors = Blue | Red
data Smells = Rose | Trash

错误信息:

test.hs:10:10:
    No instance for (StringLike Smells)
      arising from the superclasses of an instance declaration
    In the instance declaration for `IntLike Colors'
Failed, modules loaded: none.

然而,下面的代码再次编译就好了:

{-# LANGUAGE FlexibleContexts #-}


class StringLike a where
 getString :: a->String

class (StringLike Smells) =>IntLike a where
 getInt :: a-> Int


instance StringLike Colors where
 getString x = "Hello"


data Colors = Blue | Red
data Smells = Rose | Trash

第 4 部分:Haskell 报告 says

Assume that the type variables in the instance type (T u1 … uk) satisfy the constraints in the instance context cx′. Under this assumption, the following two conditions must also be satisfied:

  1. The constraints expressed by the superclass context cx[(T u1 … uk)/u] of C must be satisfied. In other words, T must be an instance of each of C's superclasses and the contexts of all superclass instances must be implied by cx′.
  2. Any constraints on the type variables in the instance type that are required for the class method declarations in d to be well-typed must also be satisfied.
本讨论的

None 假设超类上下文是报告其他地方要求的简化形式;因此可以(并且确实)作为更复杂的超类上下文的含义。