Haskell cannot do this kind of pattern matching out of the box, although there are some languages ββthat can, for example, CLIPS , for example, or F #, using active patterns .
But we can use the existing Haskell pattern matching capabilities to get a similar result. First, define a function called deconstruct, defined as follows:
deconstruct :: [a] -> [([a], a, [a])] deconstruct [] = [] deconstruct [x] = [([], x, [])] deconstruct (x:xs) = ([], x, xs) : [(x:ys1, y, ys2) | (ys1, y, ys2) <- deconstruct xs]
What this function does is get all the decompositions of the list xs into triples of the form (ys1, y, ys2) such that ys1 ++ [y] ++ ys2 == xs . For example:
deconstruct [1..4] => [([],1,[2,3,4]),([1],2,[3,4]),([1,2],3,[4]),([1,2,3],4,[])]
Using this, you can define your function as follows:
checkNotSameScope xs ne = 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
We can use do-notation to get something even closer to what you are looking for:
checkNotSameScope xs ne = BoolLit $ not $ any (alreadyThere n) prefixes where prefixes = do (xs, ("$", Undefined), _) <- deconstruct xs return xs
Here are a few things going on. First of all, the prefixes variable will store all the prefix lists that appear before the pair ("$", Undefined) , or not if the pair is not in the xs input list. Then, using the any function, we check to see if alreadyThere n True for any of the prefixes. The rest is to complete your function logic.