类型变量 #
一、类型变量基础 #
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 = (:)
十、总结 #
类型变量要点:
- 基本概念:小写字母表示类型占位符
- 参数多态:函数可以用于多种类型
- 类型约束:限制类型变量必须满足的条件
- 作用域:类型变量在签名内有效
- 高阶类型:类型变量可以是类型构造器
- 数据类型:数据定义可以使用类型参数
掌握类型变量后,让我们继续学习函数基础。
最后更新:2026-03-27