列表函数 #

一、访问函数 #

1.1 首尾元素 #

haskell
-- head:获取第一个元素
head [1, 2, 3, 4, 5]  -- 1
head "hello"          -- 'h'

-- last:获取最后一个元素
last [1, 2, 3, 4, 5]  -- 5
last "hello"          -- 'o'

-- 注意:对空列表会报错
-- head []  -- 错误!

1.2 首尾之外 #

haskell
-- tail:除第一个元素外的所有元素
tail [1, 2, 3, 4, 5]  -- [2, 3, 4, 5]
tail "hello"          -- "ello"

-- init:除最后一个元素外的所有元素
init [1, 2, 3, 4, 5]  -- [1, 2, 3, 4]
init "hello"          -- "hell"

-- 注意:对空列表会报错
-- tail []  -- 错误!

1.3 安全访问 #

haskell
-- 自定义安全版本
safeHead :: [a] -> Maybe a
safeHead []    = Nothing
safeHead (x:_) = Just x

safeTail :: [a] -> Maybe [a]
safeTail []     = Nothing
safeTail (_:xs) = Just xs

safeLast :: [a] -> Maybe a
safeLast []     = Nothing
safeLast [x]    = Just x
safeLast (_:xs) = safeLast xs

safeInit :: [a] -> Maybe [a]
safeInit []     = Nothing
safeInit [x]    = Just []
safeInit (x:xs) = (x:) <$> safeInit xs

1.4 索引访问 #

haskell
-- !! 运算符:索引访问(从0开始)
[1, 2, 3, 4, 5] !! 0  -- 1
[1, 2, 3, 4, 5] !! 2  -- 3
"hello" !! 1          -- 'e'

-- 安全索引
safeIndex :: [a] -> Int -> Maybe a
safeIndex xs n
    | n < 0 || n >= length xs = Nothing
    | otherwise               = Just (xs !! n)

二、长度与判断 #

2.1 长度函数 #

haskell
-- length:获取长度
length [1, 2, 3, 4, 5]  -- 5
length "hello"          -- 5
length []               -- 0

-- null:判断是否为空
null []      -- True
null [1, 2]  -- False
null ""      -- True

2.2 存在性判断 #

haskell
-- elem:判断元素是否存在
elem 3 [1, 2, 3, 4, 5]  -- True
elem 6 [1, 2, 3, 4, 5]  -- False
'a' `elem` "hello"      -- True

-- notElem:判断元素是否不存在
notElem 3 [1, 2, 3, 4, 5]  -- False
notElem 6 [1, 2, 3, 4, 5]  -- True

2.3 条件判断 #

haskell
-- all:所有元素满足条件
all even [2, 4, 6, 8]   -- True
all even [2, 3, 4, 5]   -- False
all (> 0) [1, 2, 3]     -- True

-- any:任一元素满足条件
any even [1, 3, 5, 6]   -- True
any even [1, 3, 5]      -- False
any (< 0) [1, 2, 3]     -- False

-- and:布尔列表全部为True
and [True, True, True]    -- True
and [True, False, True]   -- False

-- or:布尔列表任一为True
or [False, True, False]   -- True
or [False, False, False]  -- False

三、取与舍 #

3.1 固定数量 #

haskell
-- take:取前n个元素
take 3 [1, 2, 3, 4, 5]  -- [1, 2, 3]
take 10 [1, 2, 3]       -- [1, 2, 3]  -- 不会越界
take 0 [1, 2, 3]        -- []
take (-1) [1, 2, 3]     -- []

-- drop:丢弃前n个元素
drop 3 [1, 2, 3, 4, 5]  -- [4, 5]
drop 10 [1, 2, 3]       -- []
drop 0 [1, 2, 3]        -- [1, 2, 3]

-- splitAt:在指定位置分割
splitAt 3 [1, 2, 3, 4, 5]  -- ([1, 2, 3], [4, 5])
splitAt 0 [1, 2, 3]        -- ([], [1, 2, 3])
splitAt 10 [1, 2, 3]       -- ([1, 2, 3], [])

3.2 条件取舍 #

haskell
-- takeWhile:取满足条件的元素
takeWhile (< 5) [1..10]     -- [1, 2, 3, 4]
takeWhile even [2, 4, 6, 7, 8]  -- [2, 4, 6]
takeWhile (/= ' ') "hello world"  -- "hello"

-- dropWhile:丢弃满足条件的元素
dropWhile (< 5) [1..10]     -- [5, 6, 7, 8, 9, 10]
dropWhile even [2, 4, 6, 7, 8]  -- [7, 8]

-- span:分割为满足和不满足两部分
span (< 5) [1..10]   -- ([1, 2, 3, 4], [5, 6, 7, 8, 9, 10])
span even [2, 4, 6, 7, 8]  -- ([2, 4, 6], [7, 8])

-- break:span的否定
break (> 5) [1..10]  -- ([1, 2, 3, 4, 5], [6, 7, 8, 9, 10])
break even [1, 3, 5, 6, 7]  -- ([1, 3, 5], [6, 7])

3.3 分区 #

haskell
-- partition:按条件分为两部分
partition even [1..10]  -- ([2, 4, 6, 8, 10], [1, 3, 5, 7, 9])

partition (> 5) [1..10] -- ([6, 7, 8, 9, 10], [1, 2, 3, 4, 5])

四、转换函数 #

4.1 反转 #

haskell
-- reverse:反转列表
reverse [1, 2, 3, 4, 5]  -- [5, 4, 3, 2, 1]
reverse "hello"          -- "olleh"
reverse []               -- []

4.2 过滤 #

haskell
-- filter:过滤满足条件的元素
filter even [1..10]      -- [2, 4, 6, 8, 10]
filter (> 5) [1..10]     -- [6, 7, 8, 9, 10]
filter isLetter "hello123"  -- "hello"

4.3 映射 #

haskell
-- map:对每个元素应用函数
map (*2) [1, 2, 3, 4, 5]  -- [2, 4, 6, 8, 10]
map show [1, 2, 3]        -- ["1", "2", "3"]
map length ["hello", "world"]  -- [5, 5]

-- map与组合
map (show . (*2)) [1, 2, 3]  -- ["2", "4", "6"]

五、折叠函数 #

5.1 foldr #

haskell
-- foldr:右折叠
foldr (+) 0 [1, 2, 3, 4, 5]  -- 15
foldr (*) 1 [1, 2, 3, 4]     -- 24
foldr (:) [] [1, 2, 3]       -- [1, 2, 3]

-- 计算过程
-- foldr (+) 0 [1, 2, 3]
-- = 1 + (2 + (3 + 0))
-- = 6

5.2 foldl #

haskell
-- foldl:左折叠
foldl (+) 0 [1, 2, 3, 4, 5]  -- 15
foldl (*) 1 [1, 2, 3, 4]     -- 24
foldl (flip (:)) [] [1, 2, 3]  -- [3, 2, 1]

-- 计算过程
-- foldl (+) 0 [1, 2, 3]
-- = ((0 + 1) + 2) + 3
-- = 6

5.3 fold应用 #

haskell
-- 求和
sum' :: Num a => [a] -> a
sum' = foldl (+) 0

-- 求积
product' :: Num a => [a] -> a
product' = foldl (*) 1

-- 长度
length' :: [a] -> Int
length' = foldl (\acc _ -> acc + 1) 0

-- 拼接
concat' :: [[a]] -> [a]
concat' = foldr (++) []

-- 判断所有
all' :: (a -> Bool) -> [a] -> Bool
all' p = foldl (\acc x -> acc && p x) True

5.4 scan #

haskell
-- scanl:类似foldl但保留中间结果
scanl (+) 0 [1, 2, 3, 4]  -- [0, 1, 3, 6, 10]
scanl (*) 1 [1, 2, 3, 4]  -- [1, 1, 2, 6, 24]

-- scanr:类似foldr但保留中间结果
scanr (+) 0 [1, 2, 3, 4]  -- [10, 9, 7, 4, 0]

六、组合函数 #

6.1 zip系列 #

haskell
-- zip:配对两个列表
zip [1, 2, 3] ['a', 'b', 'c']  -- [(1, 'a'), (2, 'b'), (3, 'c')]
zip [1, 2, 3] ['a', 'b']       -- [(1, 'a'), (2, 'b')]

-- zipWith:配对并应用函数
zipWith (+) [1, 2, 3] [4, 5, 6]      -- [5, 7, 9]
zipWith (*) [1, 2, 3] [4, 5, 6]      -- [4, 10, 18]
zipWith (,) [1, 2, 3] ['a', 'b', 'c'] -- [(1, 'a'), (2, 'b'), (3, 'c')]

-- zip3:三个列表配对
zip3 [1, 2, 3] ['a', 'b', 'c'] [True, False, True]
-- [(1, 'a', True), (2, 'b', False), (3, 'c', True)]

6.2 unzip系列 #

haskell
-- unzip:解配对
unzip [(1, 'a'), (2, 'b'), (3, 'c')]  -- ([1, 2, 3], "abc")

-- unzip3:解三个配对
unzip3 [(1, 'a', True), (2, 'b', False)]
-- ([1, 2], "ab", [True, False])

6.3 concat系列 #

haskell
-- concat:拼接列表的列表
concat [[1, 2], [3, 4], [5, 6]]  -- [1, 2, 3, 4, 5, 6]

-- concatMap:映射后拼接
concatMap show [1, 2, 3]  -- "123"

-- 等价于
concatMap' f xs = concat (map f xs)

七、搜索函数 #

7.1 查找元素 #

haskell
import Data.List

-- find:查找满足条件的元素
find (> 3) [1, 2, 3, 4, 5]  -- Just 4
find (> 5) [1, 2, 3]        -- Nothing

-- filter:查找所有满足条件的元素
filter (> 3) [1, 2, 3, 4, 5]  -- [4, 5]

7.2 查找位置 #

haskell
import Data.List

-- elemIndex:元素位置
elemIndex 3 [1, 2, 3, 4, 5]  -- Just 2
elemIndex 6 [1, 2, 3]        -- Nothing

-- elemIndices:所有位置
elemIndices 'a' "banana"  -- [1, 3, 5]

-- findIndex:满足条件的位置
findIndex (> 3) [1, 2, 3, 4, 5]  -- Just 3

-- findIndices:满足条件的所有位置
findIndices even [1, 2, 3, 4, 5, 6]  -- [1, 3, 5]

7.3 关联列表 #

haskell
-- lookup:在关联列表中查找
lookup 2 [(1, "one"), (2, "two"), (3, "three")]  -- Just "two"
lookup 4 [(1, "one"), (2, "two")]  -- Nothing

八、排序函数 #

8.1 基本排序 #

haskell
import Data.List

-- sort:排序
sort [3, 1, 4, 1, 5, 9, 2, 6]  -- [1, 1, 2, 3, 4, 5, 6, 9]

-- sort字符串
sort "hello"  -- "ehllo"

8.2 自定义排序 #

haskell
import Data.List

-- sortBy:自定义比较
sortBy (flip compare) [1, 2, 3]  -- [3, 2, 1]  -- 降序

-- 按长度排序
sortBy (compare `on` length) ["abc", "de", "fghij"]
-- ["de", "abc", "fghij"]

-- 按元组元素排序
sortBy (compare `on` fst) [(3, 'a'), (1, 'b'), (2, 'c')]
-- [(1, 'b'), (2, 'c'), (3, 'a')]

8.3 分组 #

haskell
import Data.List

-- group:分组相邻相同元素
group [1, 1, 2, 2, 2, 3, 1, 1]
-- [[1, 1], [2, 2, 2], [3], [1, 1]]

-- groupBy:自定义分组
groupBy (\x y -> (x > 0) == (y > 0)) [-2, -1, 0, 1, 2]
-- [[-2, -1], [0], [1, 2]]

九、特殊函数 #

9.1 iterate #

haskell
-- iterate:重复应用函数
take 5 (iterate (*2) 1)  -- [1, 2, 4, 8, 16]
take 5 (iterate (++ "a") "x")  -- ["x", "xa", "xaa", "xaaa", "xaaaa"]

9.2 repeat和replicate #

haskell
-- repeat:无限重复
take 5 (repeat 1)  -- [1, 1, 1, 1, 1]

-- replicate:重复n次
replicate 5 1  -- [1, 1, 1, 1, 1]
replicate 3 'a'  -- "aaa"

9.3 cycle #

haskell
-- cycle:无限循环
take 10 (cycle [1, 2, 3])  -- [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
take 5 (cycle "ab")  -- "ababa"

十、总结 #

列表函数要点:

  1. 访问headtaillastinit!!
  2. 判断nullelemallany
  3. 取舍takedroptakeWhiledropWhile
  4. 转换mapfilterreverse
  5. 折叠foldrfoldlscanrscanl
  6. 组合zipunzipconcat
  7. 搜索findelemIndexlookup
  8. 排序sortsortBygroup

掌握列表函数后,让我们继续学习元组。

最后更新:2026-03-27