函数定义 #
一、函数基础 #
1.1 什么是函数 #
在Haskell中,函数是核心构件:
haskell
-- 函数定义
double :: Int -> Int
double x = x * 2
-- 调用
result = double 5 -- 10
1.2 函数类型签名 #
haskell
-- 基本形式:参数类型 -> 返回类型
add :: Int -> Int -> Int
add x y = x + y
-- 单参数
negate :: Int -> Int
negate x = -x
-- 多参数(柯里化)
max :: Ord a => a -> a -> a
max x y = if x >= y then x else y
1.3 无参数函数 #
haskell
-- 实际上是常量
piValue :: Double
piValue = 3.14159
-- 等价于
piValue' :: () -> Double
piValue' () = 3.14159
二、函数参数 #
2.1 位置参数 #
haskell
-- 按位置传递参数
subtract :: Int -> Int -> Int
subtract x y = x - y
-- 调用
result = subtract 10 3 -- 7
2.2 部分应用 #
haskell
-- 部分应用创建新函数
add5 :: Int -> Int
add5 = add 5
-- 使用
result = add5 10 -- 15
-- 另一个例子
multiplyBy3 :: Int -> Int
multiplyBy3 = (*3)
result2 = multiplyBy3 7 -- 21
2.3 参数命名 #
haskell
-- 常用参数命名约定
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)
-- 使用下划线表示不使用
const :: a -> b -> a
const x _ = x
三、返回值 #
3.1 隐式返回 #
Haskell函数隐式返回最后一个表达式的值:
haskell
-- 隐式返回
add x y = x + y -- 返回 x + y
-- 多行
absolute x =
if x >= 0
then x
else -x
3.2 显式返回 #
haskell
-- 使用return(IO上下文中)
import Control.Monad
ioExample :: IO String
ioExample = do
return "Hello" -- 返回字符串
3.3 返回函数 #
haskell
-- 返回函数
makeMultiplier :: Int -> (Int -> Int)
makeMultiplier n = (\x -> n * x)
-- 使用
times3 = makeMultiplier 3
times3 5 -- 15
四、函数定义方式 #
4.1 表达式定义 #
haskell
-- 简单表达式
square x = x * x
-- 复杂表达式
quadratic a b c =
let discriminant = b * b - 4 * a * c
in if discriminant < 0
then error "No real roots"
else sqrt discriminant
4.2 条件表达式 #
haskell
-- if-then-else
absolute x = if x >= 0 then x else -x
-- case表达式
describe n = case n of
0 -> "zero"
1 -> "one"
2 -> "two"
_ -> "many"
4.3 守卫表达式 #
haskell
-- 使用守卫
signum x
| x > 0 = 1
| x < 0 = -1
| otherwise = 0
-- 多守卫
grade score
| score >= 90 = 'A'
| score >= 80 = 'B'
| score >= 70 = 'C'
| score >= 60 = 'D'
| otherwise = 'F'
4.4 模式匹配 #
haskell
-- 列表模式
head' :: [a] -> a
head' (x:_) = x
head' [] = error "empty list"
-- 元组模式
fst' :: (a, b) -> a
fst' (x, _) = x
-- 嵌套模式
firstTwo :: [a] -> (a, a)
firstTwo (x:y:_) = (x, y)
firstTwo [x] = (x, x)
firstTwo [] = error "empty list"
五、递归函数 #
5.1 基本递归 #
haskell
-- 阶乘
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
-- 斐波那契
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
5.2 列表递归 #
haskell
-- 列表长度
length' :: [a] -> Int
length' [] = 0
length' (_:xs) = 1 + length' xs
-- 列表反转
reverse' :: [a] -> [a]
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
-- 列表连接
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x : append xs ys
5.3 尾递归 #
haskell
-- 尾递归版本
factorialTR :: Integer -> Integer
factorialTR n = go n 1
where
go 0 acc = acc
go n acc = go (n - 1) (n * acc)
-- 使用累加器避免栈溢出
reverseTR :: [a] -> [a]
reverseTR xs = go xs []
where
go [] acc = acc
go (x:xs) acc = go xs (x:acc)
六、函数组合 #
6.1 组合运算符 #
haskell
-- 点运算符
(.) :: (b -> c) -> (a -> b) -> (a -> c)
-- 示例
squareOfSum = square . sum
squareOfSum [1, 2, 3] = (sum [1, 2, 3]) ^ 2 = 36
6.2 管道运算符 #
haskell
-- $运算符(函数应用)
($) :: (a -> b) -> a -> b
-- 使用$避免括号
result = sum (map (*2) [1..10])
result' = sum $ map (*2) [1..10]
-- 多$连接
complicated = f $ g $ h $ x
-- 等价于
complicated' = f (g (h x))
6.3 组合示例 #
haskell
-- 常用组合
lengthEven = length . filter even
lengthEven [1..10] = 5
sumSquares = sum . map (^2)
sumSquares [1..5] = 55
composeAll = foldr (.) id
composeAll [f, g, h] = f . g . h
七、匿名函数 #
7.1 Lambda表达式 #
haskell
-- 基本形式
\x -> x + 1
-- 多参数
\x y -> x + y
-- 使用
addOne = \x -> x + 1
result = addOne 5 -- 6
7.2 Lambda与高阶函数 #
haskell
-- map中使用
map (\x -> x * 2) [1..5] -- [2, 4, 6, 8, 10]
-- filter中使用
filter (\x -> x > 3) [1..5] -- [4, 5]
-- fold中使用
foldl (\acc x -> acc + x) 0 [1..10] -- 55
7.3 Lambda与模式匹配 #
haskell
-- 带模式的lambda
first = \(x:_) -> x
-- 元组lambda
addPair = \(x, y) -> x + y
-- 多匹配lambda
-- 需要用case
describe = \x -> case x of
0 -> "zero"
_ -> "non-zero"
八、函数柯里化 #
8.1 柯里化基础 #
haskell
-- 多参数函数本质是单参数函数
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
-- 调用
add 5 3 -- 8
-- 等价于
(add 5) 3
8.2 部分应用 #
haskell
-- 创建新函数
add10 :: Int -> Int
add10 = add 10
-- 在高阶函数中使用
map (add 10) [1, 2, 3] -- [11, 12, 13]
8.3 反斜线线语法 #
haskell
-- 使用反斜线创建lambda
prefixHello = ("Hello, " ++)
suffixExclamation = (++ "!")
-- 使用
prefixHello "World" -- "Hello, World"
suffixExclamation "Hi" -- "Hi!"
九、实践示例 #
9.1 常用函数 #
haskell
-- 身份函数
id :: a -> a
id x = x
-- 常数函数
const :: a -> b -> a
const x _ = x
-- 组合函数
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
-- 翻转组合
flip :: (a -> b -> c) -> (b -> a -> c)
flip f x y = f y x
9.2 数据处理 #
haskell
-- 管道处理
process :: [Int] -> [String]
process = map show . filter even . sort
-- 使用
process [5, 2, 8, 1] -- ["2","8"]
-- 更复杂的管道
analyze :: [Double] -> Maybe Double
analyze xs
| null xs = Nothing
| otherwise = Just (sum xs / fromIntegral (length xs))
9.3 验证函数 #
haskell
-- 验证年龄
validAge :: Int -> Bool
validAge age = age >= 0 && age <= 150
-- 验证邮箱
validEmail :: String -> Bool
validEmail email =
'@' `elem` email &&
'.' `elem` dropWhile (/= '@') email
-- 验证用户名
validUsername :: String -> Bool
validUsername name =
not (null name) &&
all (`elem` validChars) name
where
validChars = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "_-"
十、总结 #
函数定义要点:
- 函数类型:使用
->连接参数和返回类型 - 参数传递:按位置传递,支持部分应用
- 返回值:隐式返回最后一个表达式
- 定义方式:表达式、守卫、模式匹配
- 递归:函数可以调用自身
- 组合:使用
.和$组合函数 - Lambda:使用
\参数 -> 表达式创建匿名函数
掌握函数基础后,让我们继续学习模式匹配。
最后更新:2026-03-27