(以下内容并不完全正确;正如 Shumush 指出的那样,模式匹配只能使用数据构造函数完成,而不仅仅是任何函数。下面提到的(:) 和 Just 是实际的数据构造函数;各种逗号函数不' 似乎不是,所以我实际上并不知道与元组匹配的模式是如何工作的。也许可以认为这是对元组模式匹配的巧合类比。)
首先,考虑模式匹配如何应用于列表,以map 的定义为例。
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x (map f xs)
在这里,您可以对列表进行模式匹配,因为(:) 是一个从一个元素和另一个列表生成列表的函数。也就是说,(x:xs) 可以通过将 1 绑定到 x 和 [2,3] 到 xs 来匹配 [1,2,3],因为 (:) 1 [2, 3] = 1 : [2,3] = [1,2,3]。
(,) 是一个产生元组的函数:
> :t (,)
(,) :: a -> b -> (a, b)
所以(,) 1 2 = (1, 2)。因此,您可以像使用 (:) 一样使用 (,) 进行模式匹配:
(skinny, normal, fat) = (18.5, 25.0, 30.0)
(Prelude 提供了(,,) :: a -> b -> c -> (a, b, c)、(,,,) 等的定义。)
将 18.5 绑定到 skinny,将 25.0 绑定到 normal,并将 30.0 绑定到 fat,因为
(,) 18.5 25.0 30.0 = (18.5, 25.0, 30.0)
将模式匹配视为函数评估的反面。您无需将函数应用于值以生成新值,而是“分解”一个值以获取用于生成该值的操作数。
模式匹配可以通过 any 函数调用来完成,这就是为什么你可以在 Maybe 值之类的东西上进行模式匹配
-- From the Functor instance of Maybe
fmap :: (a -> b) -> (Maybe a) -> (Maybe b)
fmap f Nothing = Nothing
fmap f (Just x) = f x
由于Just :: a -> Maybe a 是一个函数(特别是数据构造函数),您可以通过将Just 创建的Maybe 中包装的值绑定到x 来进行模式匹配。