简而言之:
deriving
自动为一些 Haskell 的类型类实现函数,例如Show
和Eq
。这不能用任意类型类来完成,但那些deriving
确实适用的类型类足够简单,可以自动实现。
Show
类型类定义了如何将数据类型表示为String
.
更广泛:
你熟悉类型类吗?
https://www.haskell.org/tutorial/classes.html
类型类类似于 Java 中的接口:它们定义了一些函数,任何想要使用这些函数的数据类型都可以实现这些函数。
例如,假设我们有一个这样的类:
class Comparable a where
lessThan :: a -> a -> Bool
equalsTo :: a -> a -> Bool
当心这个词class
。它意味着 Haskell 设置中的类型类,而不是您在面向对象语言中听到的典型“类”。这里a
是一种填充类型,类似于您期望模板在 C++ 中的工作方式和泛型在 Java 中的行为方式。
假设我们定义一个数据类型如下:
data Color = Red | Green | Blue
为了Comparable
与 一起工作Color
,我们实现了instance
of Comparable
:
instance Comparable Color where
lessThan Red Green = True
lessThan Red Blue = True
lessThan Green Blue = True
lessThan _ _ = False
equalsTo Red Red = True
equalsTo Green Green = True
equalsTo Blue Blue = True
equalsTo _ _ = False
粗略地说,这现在允许您“比较” Red
, Green
, 和Blue
彼此。但是有什么方法可以让 GHC 自动猜到这就是您想要的确切“顺序”?
退后一步,类型类Show
具有类似的结构:
https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Show.html#Show
class Show a where
showsPrec :: Int -> a -> ShowS
show :: a -> String
showList :: [a] -> ShowS
showsPrec _ x s = show x ++ s
show x = shows x ""
showList ls s = showList__ shows ls s
需要注意的是,类型类中的函数可以相互定义。事实上,我们也可以轻松做到:
class Comparable a where
lessThan :: a -> a -> Bool
equalsTo :: a -> a -> Bool
greaterThan :: a -> a -> Bool
greaterThan lhs rhs = not (lessThan lhs rhs && equalsTo lhs rhs)
Color
但是,关键点是:对于任意用户定义的类型类,当您尝试将类型类与诸如or之类的数据类型相关联时,GHC 不知道应该如何实现它们的功能BaseballPlayer
。对于一些功能足够简单的类型类,例如Show
, Eq
,等,GHC 可以生成默认实现,您当然可以自己覆盖这些实现。Ord
事实上,让我们尝试编译以下内容来进行实验:
data Color = Red | Green | Blue deriving (Comparable)
我得到的结果是这样的:
test.hs:9:43:
Can't make a derived instance of ‘Comparable Color’:
‘Comparable’ is not a derivable class
Try enabling DeriveAnyClass
In the data declaration for ‘Color’
当然,可以使用一些 GHC 扩展来扩展 的功能deriving
,但那是另一天 :)