自定义类型类 #

一、定义类型类 #

1.1 基本语法 #

haskell
-- 使用class定义类型类
class ClassName a where
    methodName :: TypeSignature
    methodName = defaultImplementation  -- 可选默认实现

1.2 简单示例 #

haskell
-- 定义一个可描述的类型类
class Describable a where
    describe :: a -> String

-- 实现实例
instance Describable Bool where
    describe True  = "True: yes"
    describe False = "False: no"

instance Describable Int where
    describe n = "Int: " ++ show n

-- 使用
describe True   -- "True: yes"
describe 42     -- "Int: 42"

1.3 多方法类型类 #

haskell
-- 多个方法的类型类
class Serializable a where
    serialize   :: a -> String
    deserialize :: String -> a

-- 实现实例
instance Serializable Bool where
    serialize True  = "true"
    serialize False = "false"
    deserialize "true"  = True
    deserialize "false" = False
    deserialize _       = error "Invalid boolean"

二、默认实现 #

2.1 提供默认实现 #

haskell
-- 默认实现
class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    
    -- 默认实现
    x == y = not (x /= y)
    x /= y = not (x == y)

-- 实现时只需实现一个
instance Eq Bool where
    True  == True  = True
    False == False = True
    _     == _     = False
    -- (/=) 使用默认实现

2.2 相互依赖的默认实现 #

haskell
-- 相互依赖
class Comparable a where
    compare :: a -> a -> Ordering
    (<) :: a -> a -> Bool
    (>) :: a -> a -> Bool
    
    -- 默认实现
    x < y = compare x y == LT
    x > y = compare x y == GT

-- 只需实现compare
instance Comparable Int where
    compare x y
        | x < y     = LT
        | x > y     = GT
        | otherwise = EQ

三、类型类继承 #

3.1 基本继承 #

haskell
-- 类型类继承
class Eq a => Ord a where
    compare :: a -> a -> Ordering
    (<) :: a -> a -> Bool
    -- ...

-- Ord继承Eq
-- 实现Ord必须先实现Eq

3.2 多重继承 #

haskell
-- 多重继承
class (Show a, Eq a) => PrintableEq a where
    printEq :: a -> a -> String
    printEq x y = 
        if x == y 
            then show x ++ " equals " ++ show y
            else show x ++ " not equals " ++ show y

-- 实现PrintableEq需要先实现Show和Eq
instance PrintableEq Int  -- 使用派生

3.3 继承层次 #

haskell
-- 层次结构
class Eq a where ...

class Eq a => Ord a where ...

class Ord a => Enum a where ...

-- 实现Enum需要先实现Ord和Eq

四、参数化类型类 #

4.1 单参数类型类 #

haskell
-- 单参数
class Functor f where
    fmap :: (a -> b) -> f a -> f b

-- 实现Functor
instance Functor Maybe where
    fmap _ Nothing  = Nothing
    fmap f (Just x) = Just (f x)

instance Functor [] where
    fmap = map

4.2 多参数类型类 #

haskell
{-# LANGUAGE MultiParamTypeClasses #-}

-- 多参数类型类
class Convert a b where
    convert :: a -> b

-- 实现
instance Convert Int Double where
    convert = fromIntegral

instance Convert String Int where
    convert = read

-- 使用
convert (42 :: Int) :: Double  -- 42.0

4.3 类型依赖 #

haskell
{-# LANGUAGE FunctionalDependencies #-}

-- 类型依赖
class Collection c e | c -> e where
    empty  :: c
    insert :: e -> c -> c
    member :: e -> c -> Bool

-- c -> e 表示c决定e
-- 例如:Set Int 决定元素类型是 Int

五、实践示例 #

5.1 大小类型类 #

haskell
-- 定义大小类型类
class Sizeable a where
    size :: a -> Int
    isEmpty :: a -> Bool
    isEmpty x = size x == 0

-- 实现实例
instance Sizeable [a] where
    size = length

instance Sizeable (Maybe a) where
    size Nothing  = 0
    size (Just _) = 1

instance Sizeable (Either a b) where
    size (Left _)  = 1
    size (Right _) = 1

5.2 验证类型类 #

haskell
-- 验证类型类
class Validatable a where
    validate :: a -> Maybe String  -- Nothing表示有效

-- 用户数据
data User = User
    { userName :: String
    , userAge  :: Int
    }

instance Validatable User where
    validate (User name age)
        | null name        = Just "Name cannot be empty"
        | age < 0          = Just "Age cannot be negative"
        | age > 150        = Just "Age is too high"
        | otherwise        = Nothing

5.3 编码类型类 #

haskell
-- 编码类型类
class Encodable a where
    encode :: a -> String
    decode :: String -> Maybe a

-- 实现Bool编码
instance Encodable Bool where
    encode True  = "1"
    encode False = "0"
    decode "1" = Just True
    decode "0" = Just False
    decode _   = Nothing

-- 实现Int编码
instance Encodable Int where
    encode = show
    decode s = case reads s of
        [(n, "")] -> Just n
        _         -> Nothing

5.4 数学类型类 #

haskell
-- 向量类型类
class Vector v where
    zero :: v
    add :: v -> v -> v
    scale :: Double -> v -> v
    dot :: v -> v -> Double

-- 二维向量
data Vec2 = Vec2 Double Double

instance Vector Vec2 where
    zero = Vec2 0 0
    add (Vec2 x1 y1) (Vec2 x2 y2) = Vec2 (x1 + x2) (y1 + y2)
    scale s (Vec2 x y) = Vec2 (s * x) (s * y)
    dot (Vec2 x1 y1) (Vec2 x2 y2) = x1 * x2 + y1 * y2

六、高级特性 #

6.1 关联类型 #

haskell
{-# LANGUAGE TypeFamilies #-}

-- 关联类型
class Container c where
    type Element c
    empty :: c
    insert :: Element c -> c -> c
    getElements :: c -> [Element c]

-- 实现
instance Container [a] where
    type Element [a] = a
    empty = []
    insert = (:)
    getElements = id

instance Container (Maybe a) where
    type Element (Maybe a) = a
    empty = Nothing
    insert x _ = Just x
    getElements Nothing  = []
    getElements (Just x) = [x]

6.2 关联数据类型 #

haskell
{-# LANGUAGE TypeFamilies #-}

-- 关联数据类型
class Expression e where
    data Value e
    evaluate :: e -> Value e

-- 实现
instance Expression Int where
    data Value Int = IntValue Int
    evaluate = IntValue

instance Expression Bool where
    data Value Bool = BoolValue Bool
    evaluate = BoolValue

6.3 最小完整定义 #

haskell
-- 指定最小实现
class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    
    x == y = not (x /= y)
    x /= y = not (x == y)
    
    {-# MINIMAL (==) | (/=) #-}
    -- 只需实现其中一个

七、类型类最佳实践 #

7.1 命名约定 #

haskell
-- 类型类名:大写开头,形容词或名词
class Serializable a where ...
class Comparable a where ...
class Container a where ...

-- 方法名:小写开头,动词
class Serializable a where
    serialize :: a -> String
    deserialize :: String -> Maybe a

7.2 设计原则 #

haskell
-- 好:单一职责
class Show a where
    show :: a -> String

-- 不好:太多不相关方法
class BadClass a where
    show :: a -> String
    eq :: a -> a -> Bool
    add :: a -> a -> a

7.3 提供默认实现 #

haskell
-- 好:提供合理的默认实现
class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x /= y = not (x == y)  -- 默认实现

八、总结 #

自定义类型类要点:

  1. class定义class ClassName a where ...
  2. instance实现instance ClassName Type where ...
  3. 默认实现:提供方法默认实现
  4. 继承class Super a => Sub a where ...
  5. 多参数class Class a b where ...
  6. 关联类型type Element c
  7. 最佳实践:单一职责、合理命名、提供默认

掌握自定义类型类后,让我们继续学习模块系统。

最后更新:2026-03-27