Haskell不可反驳模式匹配

zkure5ic  于 2022-11-14  发布在  其他
关注(0)|答案(3)|浏览(177)

为了在 haskell 的道路上抢先一步,我选择了它的创作者之一胡达克的这本书。所以,我正在经历对 haskell 的温和介绍。
我在试图理解下面的陈述时愣住了:
从技术上讲,形式参数也是模式,但它们永远不会与值不匹配。
根据我对C语言(或者广义地说,非函数式语言)的习惯,我可以认为形式参数是函数定义中的参数。因此,假设C中有一个函数,如下所示:

int func_add(int a, int d)

那么如果我是正确的,那么传递一个其他类型的值,比如string,将导致模式匹配失败,所以将func_add调用为func_add("trs", 5)就是模式不匹配的情况。
当一段代码通过传递不同类型的参数来调用一个函数时,这种类似的情况在Haskell中也很可能发生,但很可能会出现错误的理解或解释。
那么,为什么说在Haskell中形式参数是不可反驳的模式匹配呢?

dbf7pr2w

dbf7pr2w1#

你所描述的不是一个模式,它是一个类型。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

粗体字的元素都是 * 模式 *。但这些并非不可反驳:第一个将检查我们是否已经给了函数Red,第二个检查我们是否已经给了它Green,第三个检查值是否是Blue,最后我们有一个模式(Other s),它将与所有Other模式匹配(不管s的值是什么),因为s是一个 * 变量 *,而变量是一个不可反驳的模式:我们不对字符串的值执行任何检查。
请注意,这些检查是在 * 运行时 * 进行的:然而,如果我们调用foo "Red",我们将在 * 编译时 * 得到一个类型错误,因为Haskell编译器知道foo具有类型Color -> String
如果我们会写:

foo :: Color -> String
foo c = "Some color"
foo Red = "Red"

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

dwthyt8l

dwthyt8l2#

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

aiqt4smr

aiqt4smr3#

在Haskell中,你可以用不同的方式定义类型,其中之一就是引入一个 sum type,如下所示:

data FooBar = Foo Int | Bar Bool

您可以尝试使用模式匹配编写如下函数:

myFunction (Foo x) = x

然而,这将是一个部分匹配的函数,如果你试图用myFunction (Bar False)调用它,你会得到一个异常。
另一方面,您也可以定义单一案例总和类型,如下所示:

data MyInt = MyInt Int

在这里,您可以编写如下函数:

myFunction' (MyInt x) = x

在这里,您仍然使用模式匹配,但是由于只有一个case,所以这是一个完全匹配。如果调用代码编译,匹配不会失败。
上面的MyInt实际上只是Int的一个 Package 器,所以你可以说,如果你写一个接受Int的函数,就像这样,它是同一种模式匹配:

myFunction'' :: Int -> Int
myFunction'' x = x + 42

虽然Int没有一个值构造函数可以用来进行模式匹配,但是x是一个总是匹配Int值的模式,因此可以说函数参数是一个总是成功的匹配。

相关问题