函数定义 #

一、函数基础 #

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'] ++ "_-"

十、总结 #

函数定义要点:

  1. 函数类型:使用 -> 连接参数和返回类型
  2. 参数传递:按位置传递,支持部分应用
  3. 返回值:隐式返回最后一个表达式
  4. 定义方式:表达式、守卫、模式匹配
  5. 递归:函数可以调用自身
  6. 组合:使用 .$ 组合函数
  7. Lambda:使用 \参数 -> 表达式 创建匿名函数

掌握函数基础后,让我们继续学习模式匹配。

最后更新:2026-03-27