Haskell 更自然地表达断言
假设我写了一个函数Haskell 更自然地表达断言,haskell,pattern-matching,assertions,Haskell,Pattern Matching,Assertions,假设我写了一个函数 f [x, y] = x + y f [x, y, z] = z - x - y 这是由编译器用一行额外的内容填写的,如 f _ = error "pattern match failed" f l = assert (atLeastTwo l) $ let (x,r1) = (unsafeHead l, unsafeTail l) in let (y,r2) = (unsafeHead r1, unsafeTail
f [x, y] = x + y
f [x, y, z] = z - x - y
这是由编译器用一行额外的内容填写的,如
f _ = error "pattern match failed"
f l = assert (atLeastTwo l) $
let (x,r1) = (unsafeHead l, unsafeTail l) in
let (y,r2) = (unsafeHead r1, unsafeTail r1) in
case r2 of
[] -> x + y
(z,r3) -> assert (r3 == []) $ z - x - y
如果未导出f
,并且我知道它只能正确应用,并且函数对性能至关重要,我可能希望避免在生产代码中使用额外的模式。我可以把它改写得很不自然
f _ = error "pattern match failed"
f l = assert (atLeastTwo l) $
let (x,r1) = (unsafeHead l, unsafeTail l) in
let (y,r2) = (unsafeHead r1, unsafeTail r1) in
case r2 of
[] -> x + y
(z,r3) -> assert (r3 == []) $ z - x - y
我想做的是用一行额外的代码编写原始函数定义:
f _ = makeDemonsComeOutOfMyNose "This error is impossible."
当断言或推断的安全Haskell被启用时,以描述方式命名的神奇函数将被编译为error
,当断言被禁用时,该函数将被标记为不可访问(使模式匹配不安全)。有没有办法做到这一点,或者类似的事情
编辑
为了解决jberryman对是否存在真正的性能影响的担忧:
assert px=if p then x else makeDemonsFlyioutofmynose NO\u REAL\u DEMONS\u请“assertion failed”
,但无法根据assert
定义demon函数
GHC足够聪明,可以优化未使用的模式匹配。这里有一个简单的程序
module Foo (foo) where
data List a = Nil | Cons a (List a)
link :: List a -> List a -> List a
link Nil _ = error "link: Nil"
link (Cons a _) xs = Cons a xs
l1 = Cons 'a' (Cons 'b' Nil)
foo = link l1
这是一个非常做作的示例,但它演示了这样一种情况:GHC可以证明link
(或者在您的情况下f
)正在静态已知构造函数上被调用(或者可以通过内联、简化等证明哪种模式匹配会成功)
以下是核心输出:
foo1 :: Char
foo1 = C# 'a'
foo :: List Char -> List Char
foo = \ (ds :: List Char) -> Cons foo1 ds
错误
案例不会出现在Foo
的核心中的任何位置。因此,您可以放心,在这种情况下,使用额外的未使用模式匹配绝对不会产生性能差异。您只是出于性能原因而这样做吗?您以前是否能够测量额外案例调用错误的影响?另外,一个从未达到的案例的性能成本是多少?因为您使用的是链接列表,所以应该考虑性能级别。只有在避免任何非连续内存数据结构固有的缓存未命中的情况下,类似C的最后手段优化(我不需要,这应该是最后手段!)才有意义。@leftaroundabout,这是一个假设的示例。我怀疑这是否可能。Haskell在使用核心语言时被设计成内存安全的。我认为这太简单了。我想到的那种用例是一个模块,它实现了一个数据结构,其中包含一些应该由断言检查的不变量。内联没有帮助,因为数据结构和对其执行的操作不是静态的。好吧,你的问题是(除其他外)GHC如何处理未使用的模式匹配,我在这里展示了可以完全优化未使用的模式匹配。如果您问的是如何在没有运行时开销的情况下维护数据结构的不变量,那么您可能能够在类型级别表达这些不变量,这样在运行时就没有开销了。您具体考虑什么样的数据结构和不变量?