gaw*_*awi 29 haskell functional-programming non-exhaustive-patterns partial-functions
这是我在调用Haskell子字符串函数时为什么会得到"函数中的非详尽模式..."的后续内容?
据我所知,使用-WallGHC可以警告不详尽的模式.我想知道在默认情况下没有使它成为编译时错误的原因是什么,因为它始终可以显式定义部分函数:
f :: [a] -> [b] -> Int
f [] _ = error "undefined for empty array"
f _ [] = error "undefined for empty array"
f (_:xs) (_:ys) = length xs + length ys
Run Code Online (Sandbox Code Playgroud)
问题不是针对GHC的.
是因为......
sth*_*sth 35
在某些情况下,您不介意模式匹配不是详尽无遗的.例如,虽然这可能不是最佳实现,但我认为如果它不编译它会有所帮助:
fac 0 = 1
fac n | n > 0 = n * fac (n-1)
Run Code Online (Sandbox Code Playgroud)
这是非详尽的(负数与任何情况都不匹配)对于阶乘函数的典型用法并不重要.
此外,一般情况下,如果模式匹配是穷举的,通常也无法决定编译器:
mod2 :: Integer -> Integer
mod2 n | even n = 0
mod2 n | odd n = 1
Run Code Online (Sandbox Code Playgroud)
这里应该涵盖所有情况,但编译器可能无法检测到它.由于防护可能是任意复杂的,编译器无法始终确定模式是否详尽无遗.当然这个例子最好用它编写otherwise,但我认为它也应该以当前的形式编译.
yat*_*975 14
您可以使用-Werror将警告转换为错误.我不知道你是否可以将非详尽的模式警告变成错误,对不起!
至于你问题的第三部分:
我有时会写一些函数,这些函数往往紧密结合在一起,并且具有在Haskell中无法轻易表达的属性.这些功能中的至少一些往往具有非详尽的模式,通常是"消费者".这就出现了,例如在彼此"反转"的函数中.
玩具示例:
duplicate :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : x : (duplicate xs)
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates [] = []
removeDuplicates (x:y:xs) | x == y = x : removeDuplicates xs
Run Code Online (Sandbox Code Playgroud)
现在很容易看出它removeDuplicates (duplicate as)等于as(只要元素类型在 Eq),但通常duplicate (removeDuplicates bs)会崩溃,因为有奇数个元素或2个连续元素不同.如果它没有崩溃,那是因为它bs是由duplicate第一个地产生的(或者可能是由它产生的)!
所以我们有以下法律(不是有效的Haskell):
removeDuplicates . duplicate == id
duplicate . removeDuplicates == id (for values in the range of duplicate)
Run Code Online (Sandbox Code Playgroud)
现在,如果您想在此处阻止非详尽模式,您可以removeDuplicates返回Maybe [a],或为丢失的案例添加错误消息.你甚至可以做一些事情
newtype DuplicatedList a = DuplicatedList [a]
duplicate :: [a] -> DuplicatedList a
removeDuplicates :: Eq a => DuplicatedList a -> [a]
-- implementations omitted
Run Code Online (Sandbox Code Playgroud)
这一切都是必要的,因为在Haskell类型系统中你不能轻易地表达'是一个偶数长度的列表,连续的元素对相等'(除非你是Oleg :)
但如果你不输出,removeDuplicates我认为在这里使用非详尽的模式是完全可以的.一旦你导出它,你将失去对输入的控制,并将不得不处理丢失的情况!