Haskell无可辩驳模式匹配

Haskell无可辩驳模式匹配,haskell,functional-programming,pattern-matching,Haskell,Functional Programming,Pattern Matching,为了在哈斯克尔的道路上领先一步,我选择了哈斯克尔的一位创作者胡达克写的这本书。所以,我正在温文尔雅地介绍哈斯克尔 我无法理解以下陈述: 从技术上讲,形式参数也是模式,但它们总是与值匹配 从我对C语言(或者广义上说是非函数语言)的一点但相对较大的习惯来看,我可以得出形式参数是函数定义中的参数。假设C中有一个函数如下: int func_add(int a, int d) 如果我是正确的,那么在模式匹配中传递其他类型(如字符串)的值将是失败的。因此,调用func\u add作为func\u ad

为了在哈斯克尔的道路上领先一步,我选择了哈斯克尔的一位创作者胡达克写的这本书。所以,我正在温文尔雅地介绍哈斯克尔

我无法理解以下陈述:

从技术上讲,形式参数也是模式,但它们总是与值匹配

从我对C语言(或者广义上说是非函数语言)的一点但相对较大的习惯来看,我可以得出形式参数是函数定义中的参数。假设C中有一个函数如下:

int func_add(int a, int d) 
如果我是正确的,那么在模式匹配中传递其他类型(如字符串)的值将是失败的。因此,调用
func\u add
作为
func\u add(“trs”,5)
是一种模式不匹配的情况

在Haskell中,当一段代码通过传递不同类型的参数调用函数时,这种类似的情况也会很好地发生


那么,为什么说在Haskell中,形式参数是无可辩驳的模式匹配呢

否,传递其他类型的值不是模式匹配中的失败。这是一个类型错误,代码甚至无法编译。对于类型良好的程序,形式参数是无可辩驳的模式,这是编译器允许您运行的唯一一种程序。

您描述的是而不是模式,而是类型。Haskell也有类型,这些类型在编译时解析。每次都可以有几个模式。例如,列表定义为:

data Color = Red | Green | Blue | Other String
现在我们可以定义一个函数
foo

foo :: Color -> String
foo Red = "Red"
foo Green = "Green"
foo Blue = "Blue"
foo (Other s) = s

c
是一个无可辩驳的模式:它将匹配任何
Color
对象,因此第二行
foo-Red
永远不会匹配,因此
c
是一个无可辩驳的模式。

在Haskell中,您可以用各种方式定义类型。其中之一是引入一种求和类型,如下所示:

data FooBar = Foo Int | Bar Bool
data MyInt = MyInt Int
myFunction' (MyInt x) = x
您可以尝试使用模式匹配编写如下函数:

myFunction (Foo x) = x
myFunction'' :: Int -> Int
myFunction'' x = x + 42
然而,这将是一个部分匹配的函数,如果您尝试使用
myFunction(Bar False)
调用它,您将得到一个异常

另一方面,您还可以定义单案例和类型,如下所示:

data FooBar = Foo Int | Bar Bool
data MyInt = MyInt Int
myFunction' (MyInt x) = x
在这里,您可以编写如下函数:

data FooBar = Foo Int | Bar Bool
data MyInt = MyInt Int
myFunction' (MyInt x) = x
在这里,您仍然使用模式匹配,但由于只有一种情况,所以这是一个完全匹配。如果调用代码已编译,则匹配不会失败

上面的
MyInt
实际上只是
Int
的一个包装器,因此您可以说,如果您编写的函数采用
Int
,就像这样,它是相同类型的模式匹配:

myFunction (Foo x) = x
myFunction'' :: Int -> Int
myFunction'' x = x + 42

虽然
Int
没有可用于模式匹配的值构造函数,
x
是始终匹配
Int
值的模式。因此,您可以说函数参数总是成功的匹配。

在某种意义上,您可以将其归结为“变量是无可辩驳的,文字是可辩驳的,如果任何部分是可辩驳的,则组合是可辩驳的”。对于只有一个构造函数(如元组)的类型,一个看似可反驳的模式,如
(x,y)
(或者,可以重写,
(,)x y
,一个可反驳的文本后跟两个不可反驳的变量)可以被认为是不可反驳的,因为在类型检查之后,只有
(,)
创建的值是合法的,形式参数是不可辩驳的,因为它是一个变量。只有在函数式语言(或类型良好或严格类型的语言)的情况下,这才是编译错误……对吗?我猜在“c”中,编译器不会检查这个。@Wilhem:简单地说,类型检查是在编译时完成的。因此,当传递数据构造函数中列出的值时,将验证对“foo”的调用。@Wilhem:在这种情况下,模式匹配用于评估函数的结果。但我想我不明白形式参数是无可辩驳的。你能再告诉我一点吗?像
c
这样的变量是无可辩驳的,因为它匹配所有可能的输入类型(满足类型约束)。@Wilhelm:好的。我能断定“c”是这里的形式参数吗?@AgniveshSingh:是的。Seeman:t非常感谢,但我想我需要对类型构造函数和数据构造函数有更多的了解,才能完全理解你的答案。