为什么函数名称在
中重复示例:
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
什么时候不应该重复功能名称?这是什么意思?
感谢
答案 0 :(得分:3)
您所看到的是模式匹配。
我会告诉你另一个例子:
test 1 = "one"
test 2 = "two"
test 3 = "three"
ghci中的演示:
ghci> test 1
"one"
ghci> test 2
"two"
ghci> test 3
"three"
ghci> test 4
"*** Exception: Non-exhaustive patterns in function test
因此,当您调用任何函数时,运行时系统将尝试匹配
具有已定义函数的输入。所以打电话给test 3
会
最初检查test 1
,由于1
不等于3
,它会
继续下一个定义。由于2
不等于3
,
它将进入下一个定义。在3
以来的下一个定义中
等于3
它将返回"three"
字符串。当你尝试
模式匹配程序中根本不存在的东西
抛出异常。
答案 1 :(得分:3)
这种模式匹配可以转换为case
语句(事实上,这就是编译器通常会做的事情!):
lucky' n = case n of
7 -> "LUCKY NUMBER SEVEN!"
x -> "Sorry, you're out of luck, pal!"
由于x
并未真正使用,您通常会改为_ -> "Sorry, ..."
。
请注意, 2 与
相同lucky'' n = if n==7 then ...
与(==)
的平等比较通常比模式匹配更昂贵 1 ,并且也更加丑陋。
<小时/> 1 为什么它更贵:假设我们有一个大数据结构。为了确定它们是相同的,程序将需要挖掘两个整个结构,确保所有分支都是相同的。但是,如果你模式匹配,你只需比较你现在感兴趣的一小部分。
2 实际上,在这种情况下是相同的,但仅仅因为编译器在数字上有一个特殊的模式匹配技巧:它用{{1重写它}}。这对于(==)
类型来说非常特殊,对于其他任何类型都不是。 (除非您使用the OverloadedStrings
extension。)
答案 2 :(得分:2)
我假设你在看learn you a haskell。在那个例子之后,它说
当你打电话给幸运时,将从上到下检查图案,当它符合图案时,将使用相应的功能体。
因此第一行表示函数的类型,后面的行是要检查的模式。每一行都有函数名,所以编译器知道你还在谈论相同的函数。
以这种方式思考:当您编写表达式lucky (a+b)
或其他任何内容时,编译器将尝试将lucky (a+b)
替换为函数定义中=
之前的第一个内容“适合。”因此,如果a=3
和b=4
,您将获得以下一系列替换:
lucky (a+b) =
lucky (3+4) =
--pattern matching occurs...
lucky 7 =
"LUCKY NUMBER SEVEN!"
这是使Haskell在实践中如此容易推理的部分原因;你得到一个与数学类似的系统。
答案 3 :(得分:2)
lucky
的定义使用&#34;模式匹配&#34;和等于(在这种情况下)
lucky :: (Integral a) => a -> String
lucky a = if a == 7
then "LUCKY NUMBER SEVEN!"
else "Sorry, you're out of luck, pal!"