哪些语言扩展可以编写 "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
表示 如果 a
是 MyClass
则 a
必须是 Eq
的实例,左侧 Eq a
(意味着 a
是 Eq
的实例)是谓词如果右侧为真 MyClass a
(意味着 a
是 MyClass
的实例),则必须为真。
所以换句话说,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:
- 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′
.
- 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 假设超类上下文是报告其他地方要求的简化形式;因此可以(并且确实)作为更复杂的超类上下文的含义。
我试图理解以下 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
表示 如果 a
是 MyClass
则 a
必须是 Eq
的实例,左侧 Eq a
(意味着 a
是 Eq
的实例)是谓词如果右侧为真 MyClass a
(意味着 a
是 MyClass
的实例),则必须为真。
所以换句话说,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 contextcx′
. Under this assumption, the following two conditions must also be satisfied:
- The constraints expressed by the superclass context
cx[(T u1 … uk)/u]
ofC
must be satisfied. In other words,T
must be an instance of each ofC
's superclasses and the contexts of all superclass instances must be implied bycx′
.- 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 假设超类上下文是报告其他地方要求的简化形式;因此可以(并且确实)作为更复杂的超类上下文的含义。