在Haskell中,为什么不是
这是我为什么在调用Haskell子字符串函数时得到“函数中的非穷举模式”的后续行为?
据我所知,使用-Wall
,GHC可以对非详尽的模式提出警告。 我想知道是什么原因导致默认情况下没有编译时错误,因为总是可以显式定义一个部分函数:
f :: [a] -> [b] -> Int
f [] _ = error "undefined for empty array"
f _ [] = error "undefined for empty array"
f (_:xs) (_:ys) = length xs + length ys
这个问题不是GHC特有的。
是因为...
有些情况下您不介意模式匹配不完全。 例如,虽然这可能不是最佳实现,但如果它不编译,我认为它不会有帮助:
fac 0 = 1
fac n | n > 0 = n * fac (n-1)
这是非详尽的(负数不符合任何情况)对于阶乘函数的典型用法无关紧要。
另外,如果模式匹配是详尽的,则可能通常不可能决定编译器:
mod2 :: Integer -> Integer
mod2 n | even n = 0
mod2 n | odd n = 1
这里应该涵盖所有的情况,但编译器可能无法检测到它。 由于守卫可能是任意复杂的,编译器不能总是决定模式是否详尽。 当然这个例子最好用otherwise
写,但我认为它也应该以当前的形式编译。
您可以使用-Werror
将警告转化为错误。 我不知道你是否可以将非详尽的模式警告转化为错误,对不起!
至于你的问题的第三部分:
我有时会写一些函数,这些函数倾向于紧密合作,并且具有Haskell无法轻易表达的属性。 至少其中一些功能倾向于具有非穷举模式,通常是“消费者”。 这就出现了,例如在相互“逆转”的函数中。
一个玩具的例子:
duplicate :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : x : xs
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates [] = []
removeDuplicates (x:y:xs) | x == y = x : removeDuplicates xs
现在很容易看出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)
现在,如果你想在这里防止非详尽的模式,你可以使removeDuplicates
返回Maybe [a]
,或者为失踪案例添加错误消息。 你甚至可以做一些事情
newtype DuplicatedList a = DuplicatedList [a]
duplicate :: [a] -> DuplicatedList a
removeDuplicates :: Eq a => DuplicatedList a -> [a]
-- implementations omitted
所有这些都是必须的,因为你不能在Haskell类型系统中容易地表达'是连续长度单元列表',除非你是Oleg :)
但是如果你不导出removeDuplicates
我认为在这里使用非穷举模式是完全可以的。 只要您将其导出,您将失去对输入的控制,并且将不得不处理丢失的案例!
上一篇: In Haskell, why non