我有一个函数 foo::[Integer] -> Bool ,但只有当传入参数对于某些条件有效时它才有效,否则它应该立即终止。
foo x | not $ isSorted x = False
| otherwise = some_recursive_stuff_here
where
isSorted ax = ax == sort ax
等等
但我不想每次都检查不变式是否已排序。除了引入另一个内部函数之外,是否有一个好的方法来处理这个问题?
最佳答案
您可以通过创建一个newtype
来携带您的不变量所持有的“证明”。
newtype Sorted a = Sorted { fromSorted :: [a] }
sorted :: Ord a => [a] -> Sorted a
sorted = Sorted . sort
foo :: Sorted Integer -> Bool
foo (Sorted as) -> some_recursive_stuff_here
如果您将 Sorted
构造函数隐藏在单独的模块中,那么您的代码的用户在不先创建排序证明的情况下将无法使用 foo
。他们也无法对已排序
进行排序
,因此您可以确定它只发生一次。
如果您愿意,您甚至可以支持证明维护操作。
instance Monoid (Sorted a) where
mempty = Sorted mempty
mappend (Sorted as) (Sorted bs) = Sorted (go as bs) where
-- lazy stable sort
go :: Ord a => [a] -> [a] -> [a]
go [] xs = xs
go xs [] = xs
go (x:xs) (y:ys) | x == y = x : y : go xs ys
| x < y = x : go xs (y:ys)
| x > y = y : go (x:xs) ys
(此代码现已在 Hackage 上提供: http://hackage.haskell.org/package/sorted )
关于function - 在 haskell 中检查函数参数的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19869902/