Ton*_*ion 39 haskell functional-programming pattern-matching
Haskell中的模式匹配是什么?它与保护方程有什么关系?
我试过寻找一个简单的解释,但我还没找到.
编辑:有人标记为家庭作业.我不再去上学了,我只是在学习Haskell,而我正在努力理解这个概念.纯粹出于兴趣.
out*_*tis 63
简而言之,模式就像在数学中定义分段函数一样.您可以使用模式为不同的参数指定不同的函数体.调用函数时,通过将实际参数与各种参数模式进行比较来选择适当的主体.阅读Haskell的温和介绍以获取更多信息.
相比:
与等效的Haskell:
fib 0 = 1
fib 1 = 1
fib n | n >= 2
= fib (n-1) + fib (n-2)
Run Code Online (Sandbox Code Playgroud)
请注意" ñ ≥2"中的分段函数成为Haskell的版本保护,但其他两个条件只是模式.模式是测试值和结构,如条件x:xs
,(x, y, z)
或Just x
.在分段定义中,基于=
或?
关系的条件(基本上,说"某事物"的条件)成为模式.警卫允许更一般的条件.我们可以重写fib
使用警卫:
fib n | n == 0 = 1
| n == 1 = 1
| n >= 2 = fib (n-1) + fib (n-2)
Run Code Online (Sandbox Code Playgroud)
Nor*_*sey 25
还有其他好的答案,所以我会给你一个非常技术性的答案.模式匹配的是消除结构的代数数据类型:
"消除构造"意味着"如何消费或使用价值"
除了一流函数之外,"代数数据类型"是静态类型函数语言(如Clean,F#,Haskell或ML)的重要思想.
代数数据类型的想法是你定义一种事物,然后你说出你可以做出的所有方法.例如,让我们将"字符串序列"定义为代数数据类型,有三种方法可以实现:
data StringSeq = Empty -- the empty sequence
| Cat StringSeq StringSeq -- two sequences in succession
| Single String -- a sequence holding a single element
Run Code Online (Sandbox Code Playgroud)
现在,这个定义有各种各样的错误,但作为一个例子,它很有趣,因为它提供了任意长度序列的恒定时间连接.(还有其他的方法来实现这一点.)的声明引入Empty
,Cat
和Single
,它们都是有的方式制备序列.(这使得每一个都成为一种介绍构造 - 一种制作东西的方法.)
Cat
,您需要另外两个序列.Single
,需要一个元素(在本例中为字符串)这里有一个妙语:消除构造,模式匹配,为您提供一种方法来仔细检查序列并询问它是什么构造函数?.因为您必须为任何答案做好准备,所以您为每个构造函数提供至少一个替代方案.这是一个长度函数:
slen :: StringSeq -> Int
slen s = case s of Empty -> 0
Cat s s' -> slen s + slen s'
Single _ -> 1
Run Code Online (Sandbox Code Playgroud)
在语言的核心,所有模式匹配都建立在这个case
结构上.但是,由于代数数据类型和模式匹配对于语言的习语非常重要,因此在函数定义的声明形式中进行模式匹配时会有特殊的"语法糖":
slen Empty = 0
slen (Cat s s') = slen s + slen s'
slen (Single _) = 1
Run Code Online (Sandbox Code Playgroud)
使用这种语法糖,通过模式匹配计算看起来很像通过方程定义.(Haskell委员会是故意这样做的.)正如你在其他答案中所看到的那样,case
通过在其上打一个警卫,可以将表达式或表达式中的替代方法专门化.我不能想到序列示例的合理守护,其他答案中有很多例子,所以我会留在那里.
C. *_*ann 12
至少在Haskell中,模式匹配与代数数据类型的概念密切相关.当您声明这样的数据类型时:
data SomeData = Foo Int Int
| Bar String
| Baz
Run Code Online (Sandbox Code Playgroud)
...它定义Foo
,Bar
和Baz
作为构造函数 -不要与OOP中的"构造函数"混淆 - 用SomeData
其他值构造一个值.
模式匹配只不过是反过来 -一个模式会将一个SomeData
值"解构" 成它的组成部分(事实上,我相信模式匹配是在Haskell中提取值的唯一方法).
当一个类型有多个构造函数时,你为每个模式编写一个函数的多个版本,根据使用的构造函数选择正确的函数(假设你已经编写了匹配所有可能结构的模式 - 这通常是好的做练习).