类型变量 #

一、类型变量基础 #

1.1 什么是类型变量 #

类型变量是小写字母表示的类型占位符:

haskell
-- a 是类型变量
identity :: a -> a
identity x = x

-- 可以用于任何类型
-- identity 5      :: Int -> Int
-- identity "hi"   :: String -> String
-- identity True   :: Bool -> Bool

1.2 常用类型变量命名 #

haskell
-- 常用单字母
a, b, c  -- 通用类型变量
m        -- Monad类型
f        -- Functor类型
t        -- 通用类型

-- 有意义的命名
element  -- 元素类型
key      -- 键类型
value    -- 值类型
result   -- 结果类型

1.3 多个类型变量 #

haskell
-- 两个类型变量
pair :: a -> b -> (a, b)
pair x y = (x, y)

-- 三个类型变量
triple :: a -> b -> c -> (a, b, c)
triple x y z = (x, y, z)

-- 类型变量可以相同
same :: a -> a -> (a, a)
same x y = (x, y)

二、参数多态 #

2.1 完全多态 #

没有任何约束的类型变量:

haskell
-- 完全多态函数
identity :: a -> a
identity x = x

-- 不能对x做任何假设
-- 只能原样返回

2.2 列表函数多态 #

haskell
-- 长度函数
length :: [a] -> Int
length []     = 0
length (_:xs) = 1 + length xs

-- 反转函数
reverse :: [a] -> [a]
reverse []     = []
reverse (x:xs) = reverse xs ++ [x]

-- 拼接函数
(++) :: [a] -> [a] -> [a]
[]     ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)

2.3 元组函数多态 #

haskell
-- 取第一个元素
fst :: (a, b) -> a
fst (x, _) = x

-- 取第二个元素
snd :: (a, b) -> b
snd (_, y) = y

-- 交换元组
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)

三、类型类约束 #

3.1 单一约束 #

haskell
-- Eq约束
elem :: Eq a => a -> [a] -> Bool
elem _ []     = False
elem x (y:ys) = x == y || elem x ys

-- Ord约束
maximum :: Ord a => [a] -> a
maximum []     = error "empty list"
maximum (x:xs) = foldr max x xs

-- Show约束
print :: Show a => a -> IO ()
print x = putStrLn (show x)

3.2 多重约束 #

haskell
-- 多个约束
sort :: Ord a => [a] -> [a]
sort = ...

-- 多个不同约束
showSorted :: (Ord a, Show a) => [a] -> String
showSorted xs = show (sort xs)

-- 复杂约束
process :: (Eq a, Ord a, Show a) => [a] -> String
process xs = show (nub (sort xs))

3.3 约束传播 #

haskell
-- 约束会传播到调用者
contains :: Eq a => a -> [a] -> Bool
contains x xs = elem x xs  -- elem需要Eq约束

-- 调用者也需要Eq约束
checkList :: Eq a => [a] -> a -> Bool
checkList xs x = contains x xs

四、类型变量作用域 #

4.1 函数级别 #

haskell
-- 类型变量在函数签名内有效
function :: a -> a -> b -> b
function x _ y = y  -- x的类型a与返回类型b无关

-- 不同函数的类型变量独立
func1 :: a -> a
func1 x = x

func2 :: a -> a  -- 这个a与func1的a无关
func2 x = x

4.2 数据类型级别 #

haskell
-- 数据类型中的类型变量
data Maybe a = Nothing | Just a

data Either a b = Left a | Right b

data List a = Nil | Cons a (List a)

4.3 类型类级别 #

haskell
-- 类型类中的类型变量
class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool

class Functor f where
    fmap :: (a -> b) -> f a -> f b

五、高阶类型变量 #

5.1 类型构造器 #

haskell
-- Maybe是类型构造器
-- Maybe Int 是具体类型

-- 类型变量可以是类型构造器
class Functor f where
    fmap :: (a -> b) -> f a -> f b

-- f是类型构造器变量
-- Maybe、[]、IO都是Functor实例

5.2 Kind系统 #

haskell
-- Kind是类型的类型
-- * 表示具体类型
-- Int :: *
-- String :: *

-- 箭头Kind
-- Maybe :: * -> *
-- [] :: * -> *
-- Either :: * -> * -> *

-- 在GHCi中查看
-- :kind Maybe
-- Maybe :: * -> *

5.3 高阶Kind #

haskell
-- Monad类需要 * -> * 的类型
class Monad m where
    return :: a -> m a
    (>>=)  :: m a -> (a -> m b) -> m b

-- Maybe :: * -> *,可以作为Monad
-- Int :: *,不能作为Monad

六、多态数据类型 #

6.1 参数化数据类型 #

haskell
-- 带类型参数的数据类型
data Maybe a = Nothing | Just a

data Either a b = Left a | Right b

data Pair a b = Pair a b

-- 使用
maybeInt :: Maybe Int
maybeInt = Just 5

eitherStrInt :: Either String Int
eitherStrInt = Right 42

6.2 递归数据类型 #

haskell
-- 列表
data List a = Nil | Cons a (List a)

-- 二叉树
data Tree a = Leaf | Node a (Tree a) (Tree a)

-- 使用
tree :: Tree Int
tree = Node 5 (Node 3 Leaf Leaf) (Node 7 Leaf Leaf)

6.3 记录语法 #

haskell
-- 带类型参数的记录
data Person a = Person
    { name :: String
    , age  :: Int
    , extra :: a
    }

-- 使用
person :: Person String
person = Person "John" 30 "Developer"

七、类型变量实例 #

7.1 列表函数 #

haskell
-- map
map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs

-- filter
filter :: (a -> Bool) -> [a] -> [a]
filter _ []     = []
filter p (x:xs)
    | p x       = x : filter p xs
    | otherwise = filter p xs

-- foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z []     = z
foldr f z (x:xs) = f x (foldr f z xs)

7.2 Maybe函数 #

haskell
-- fmap for Maybe
instance Functor Maybe where
    fmap _ Nothing  = Nothing
    fmap f (Just x) = Just (f x)

-- fromMaybe
fromMaybe :: a -> Maybe a -> a
fromMaybe def Nothing  = def
fromMaybe _   (Just x) = x

-- catMaybes
catMaybes :: [Maybe a] -> [a]
catMaybes = map fromJust . filter isJust
  where
    fromJust (Just x) = x
    isJust Nothing  = False
    isJust (Just _) = True

7.3 Either函数 #

haskell
-- fmap for Either
instance Functor (Either e) where
    fmap _ (Left x)  = Left x
    fmap f (Right y) = Right (f y)

-- partition
partitionEithers :: [Either a b] -> ([a], [b])
partitionEithers = foldr select ([], [])
  where
    select (Left x)  (ls, rs) = (x:ls, rs)
    select (Right y) (ls, rs) = (ls, y:rs)

八、类型变量与类型推断 #

8.1 推断规则 #

haskell
-- 编译器推断类型变量
identity x = x
-- 推断为:a -> a

-- 根据使用推断
apply f x = f x
-- 推断为:(a -> b) -> a -> b

-- 约束推断
isEqual x y = x == y
-- 推断为:Eq a => a -> a -> Bool

8.2 单态性限制 #

haskell
-- 没有类型签名的绑定可能受限
-- mono = identity
-- 可能被限制为特定类型

-- 解决方法:添加类型签名
mono :: a -> a
mono = identity

8.3 类型默认 #

haskell
-- 模糊类型使用默认
showNum = show 42
-- 默认为Integer

-- 自定义默认
default (Int, Double)

九、高级类型变量 #

9.1 显式全称量化 #

haskell
{-# LANGUAGE ExplicitForAll #-}

-- 显式声明类型变量范围
identity :: forall a. a -> a
identity x = x

-- 多个类型变量
pair :: forall a b. a -> b -> (a, b)
pair x y = (x, y)

9.2 高阶量化 #

haskell
{-# LANGUAGE RankNTypes #-}

-- 高阶类型
apply :: (forall a. a -> a) -> Int -> Int
apply f x = f x

-- 使用
test = apply identity 5

9.3 类型族 #

haskell
{-# LANGUAGE TypeFamilies #-}

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

instance Container [a] where
    type Element [a] = a
    empty = []
    insert = (:)

十、总结 #

类型变量要点:

  1. 基本概念:小写字母表示类型占位符
  2. 参数多态:函数可以用于多种类型
  3. 类型约束:限制类型变量必须满足的条件
  4. 作用域:类型变量在签名内有效
  5. 高阶类型:类型变量可以是类型构造器
  6. 数据类型:数据定义可以使用类型参数

掌握类型变量后,让我们继续学习函数基础。

最后更新:2026-03-27