哈斯克尔不能做这样的尽管有些语言可以像CLIPS或F#那样使用active patterns。
但是我们可以使用Haskell现有的模式匹配功能来获得相似的结果。让我们先来定义这样定义的函数调用解构:
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 = BoolLit $ not $ any (alreadyThere n) prefixes
where
prefixes = do
(xs, ("$", Undefined), _) <- deconstruct xs
return xs
:
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获得的东西更接近你在找什么
这里有几件事情正在进行。首先prefixes
变量将存储在("$", Undefined)
对之前出现的所有前缀列表 - 如果该对不在输入列表xs
中,则该变量将不存在。然后使用any函数我们正在检查alreadyThere n
是否给我们任何前缀的True。剩下的就是完成你的函数的逻辑。
也许我应该问,“我怎样才能做到这一点没有模式匹配的另一种方式,因为这是不可能的?”哈斯克尔是非常聪明的人。 – nicole