Haskell中Class的概念
Haskell中的Class设计与面向对象的语言有本质区别,并不是同一个概念。
比如,在Java当中,class用于定义一个物件(Object),而Haskell中的class用于表示一组功能(Functional)。
从这点来讲,Haskell的class更类似于Java中的interface,但是Java当中的interface是围绕着一个Object来设计的一组功能,而Haskell中的class是按照功能来划分出来的一组函数。
比如,在Java当中,我们可以写一个Color的class,用于描述颜色,以及对颜色的操作等等。这种思考方式叫做Object-Oriented(面向对象)。
在Haskell当中,我们不这样思考问题。我们会把一组有相关性的功能抽象出来,形成class。
比如Haskell自带的这两个class:
- Eq class:这个class定义了几个方法,用于判断数值关系,比如”大于”,”小于”,”等于”。
- Ord class:这个class定义了一些方法,用于表示顺序,以及排序。
我们可以使用ghci中的:info
命令来查看一下Eq
和Ord
两个class,并看一看它们的设计思想:
Prelude> :info Eq
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
...
上面是Eq class
的输出片段,我们看到Eq
里面定义了两个函数,分别是==
和/=
。这两个函数的功能就是用于判断”等于”和”不等于”。
上面的函数当中并且没有定义具体的类型,两个函数的参数返回值定义都是:a -> a -> Bool
。
也就是接受两个相同类型的数据,然后返回Bool
,也就是True/False
类型的数据。
Eq类型因此定义了一种”行为”:判断相等性。
此外,Eq类型没有定义具体如何实现==
和/=
,它只是定义了这两个函数要接受两个参数,给出比较结果,具体的实现交给具体的数据类型(data type)。
可以看到,Haskell的class是一种很抽象的函数类型定义。能达到这样的抽象程度,是被Haskell的整套类型系统支撑起来的。
在Java里面,实现interface的叫做class。
在Haskell里面,实现了class的叫做class instance。
我们可以看看具体实现了Eq class
的instances。可以使用:info Eq
来查看Eq class
中包含哪些实现了它的instances:
Prelude> :info Eq
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
{-# MINIMAL (==) | (/=) #-}
-- Defined in ‘GHC.Classes’
instance (Eq a, Eq b) => Eq (Either a b)
-- Defined in ‘Data.Either’
instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
instance Eq Word -- Defined in ‘GHC.Classes’
instance Eq Ordering -- Defined in ‘GHC.Classes’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Eq Float -- Defined in ‘GHC.Classes’
instance Eq Double -- Defined in ‘GHC.Classes’
instance Eq Char -- Defined in ‘GHC.Classes’
instance Eq Bool -- Defined in ‘GHC.Classes’
如上所示,我们可以看到有很多instances实现(derive)了Eq class
,比如Int
,Float
,Double
等等,它们都是Eq class
的instances。
我们使用:info
命令来看看Int
:
Prelude> :info Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
从上面的命令中,我们可以看到Int
类型是一个具体的数据类型(data Int),而不像Eq
的定义那样是个class(class Eq a where ...
)。
此外,我们看到,Int
除了实现了Eq class
,还实现了很多其它的classes,比如Enum
,Ord
,Show
等等。
在Haskell当中,我们称Int
是derive了Show
,Ord
,Eq
这些classes,也可以说Int
是Ord
,Show
,Eq
这些classes的instance。
而Int
自身叫做data type。
从上面的分析可以看到,Haskell的class和面向对象语言中的class有本质不同:Haskell的class定义功能行为,而不抽象出一个物件(object)。这就是functional language和object oriented language的一个本质区别。