Haskell 不能开箱即用地进行这种模式匹配,尽管有一些语言可以使用active patterns ,例如CLIPS或 F# 。
但是我们可以使用 Haskell 现有的模式匹配能力来获得类似的结果。让我们首先定义一个名为 deconstruct 的函数,定义如下:
deconstruct :: [a] -> [([a], a, [a])]
deconstruct [] = []
deconstruct [x] = [([], x, [])]
deconstruct (x:xs) = ([], x, xs) : [(x:ys1, y, ys2) | (ys1, y, ys2) <- deconstruct xs]
这个函数所做的是将列表 xs 的所有分解为形式的三元组,(ys1, y, ys2)
使得ys1 ++ [y] ++ ys2 == xs
. 例如:
deconstruct [1..4] => [([],1,[2,3,4]),([1],2,[3,4]),([1,2],3,[4]),([1,2,3],4,[])]
使用它,您可以按如下方式定义您的函数:
checkNotSameScope xs n e =
case [ys | (ys, ("$", Undefined), _) <- deconstruct xs] of
[ys] -> BoolLit $ not $ alreadyThere n xs
_ -> -- handle the case when ("$", Undefined) doesn't occur at all or more than once
我们可以使用do-notation来获得更接近您正在寻找的东西:
checkNotSameScope xs n e = BoolLit $ not $ any (alreadyThere n) prefixes
where
prefixes = do
(xs, ("$", Undefined), _) <- deconstruct xs
return xs
这里发生了几件事。首先,该prefixes
变量将存储出现在该("$", Undefined)
对之前的所有前缀列表 - 如果该对不在输入列表中,则没有xs
。然后使用any函数,我们正在检查是否alreadyThere n
为任何前缀提供 True 。剩下的就是完成你的函数逻辑。