模式匹配如何与列表一起使用

时间:2014-02-15 05:43:44

标签: list haskell pattern-matching

我刚开始学习haskell和模式匹配。我只是不明白它是如何实现的,[](x:_)是否因为多态性而对这个模式的不同类型和函数实现进行了求值,或者我只是错了并且使用了另一种技术。

head' :: [a] -> a  
head' [] = error "Can't call head on an empty list, dummy!"  
head' (x:_) = x 

或者让我们考虑一下这种模式匹配功能:

tell :: (Show a) => [a] -> String  
tell [] = "The list is empty"  
tell (x:[]) = "The list has one element: " ++ show x  
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y  
tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y 

我认为我错了,因为每个具有不同数量元素的列表都不能具有不同的类型。你能解释一下haskell如何知道哪些模式对某些函数实现是正确的?我理解它在逻辑上如何运作但不深入。请解释一下。

2 个答案:

答案 0 :(得分:6)

Haskell中的语法与运行时的实现之间存在一定程度的间接性。您在大多数源代码中看到的列表语法实际上是实际上相当常规的数据类型的糖。以下两行是等效的:

data List a = Nil | Cons a (List a)
data [a] = [] | a : [a]  -- pseudocode

因此,当您输入[a,b,c]时,这会将内部表示转换为(a : (b : (c : [])))

您在顶级绑定中看到的模式匹配也是一些语法语句(没有一些细微的细节),用于将数据类型解构为模式匹配的右侧的数据类型。 _符号是用于匹配任何表达式的通配符模式的内置符号(只要模式是良好类型的),但确实将一个变量添加到RHS范围。

head :: [a] -> a
head x = case x of
  (a : _) -> a
  

我认为我错了,因为每个具有不同数量元素的列表都不能具有不同的类型。你能解释一下haskell如何知道哪种模式对某些函数实现是正确的?

因此,要回答您的问题,[](x:_)属于同一类型(即我们上例中的[a]List a。 list数据类型也是递归的,因此类型a的Cons'ing值的所有递归组合都具有相同的类型,即[a]

当编译器对case语句进行类型检查时,它会沿着每个LHS列运行,并确保所有类型都是等效的,或者可以使用称为统一的过程使其等效。在案件的右侧也是如此。

Haskell“知道”通过顺序尝试每个分支并解压缩匹配的值来查看哪个模式是正确的,以查看它是否具有与模式相同数量的cons元素,然后继续执行分支,或者使用模式匹配失败如果没有匹配则出错。对数据类型的任何模式匹配都进行相同的处理,而不仅仅是列表。

答案 1 :(得分:1)

有两套独立的支票:

在编译时(在程序运行之前),编译器只是检查案例的类型是否符合函数的签名,以及对函数的调用是否符合函数的签名。

在运行时,当我们访问实际输入时,会执行类似但不同的检查集:这些检查采用手边的* actual *输入(不是其类型)并确定哪些情况与之匹配

所以,回答你的问题:决定是在编译时做出的,我们不仅有类型,还有实际价值。