- removeFL :: (MyEq p, Commute p) => p x y -> FL p x z -> Maybe (FL p y z)
- removeRL :: (MyEq p, Commute p) => p y z -> RL p x z -> Maybe (RL p x y)
- removeCommon :: (MyEq p, Commute p) => (FL p :\/: FL p) x y -> (FL p :\/: FL p) x y
- commuteWhatWeCanFL :: Commute p => (p :> FL p) x y -> (FL p :> (p :> FL p)) x y
- commuteWhatWeCanRL :: Commute p => (RL p :> p) x y -> (RL p :> (p :> RL p)) x y
- genCommuteWhatWeCanRL :: (forall a b. (p :> p) a b -> Maybe ((p :> p) a b)) -> (RL p :> p) x y -> (RL p :> (p :> RL p)) x y
- partitionFL :: Commute p => (forall u v. p u v -> Bool) -> FL p x y -> (FL p :> (FL p :> FL p)) x y
- partitionRL :: Commute p => (forall u v. p u v -> Bool) -> RL p x y -> (RL p :> RL p) x y
- simpleHeadPermutationsFL :: Commute p => FL p x y -> [FL p x y]
- headPermutationsRL :: Commute p => RL p x y -> [RL p x y]
- headPermutationsFL :: Commute p => FL p x y -> [(p :> FL p) x y]
- removeSubsequenceFL :: (MyEq p, Commute p) => FL p a b -> FL p a c -> Maybe (FL p b c)
- removeSubsequenceRL :: (MyEq p, Commute p) => RL p ab abc -> RL p a abc -> Maybe (RL p a ab)
- partitionConflictingFL :: (Commute p1, Invert p1) => CommuteFn p1 p2 -> FL p1 x y -> p2 x z -> (FL p1 :> FL p1) x y
- type CommuteFn p1 p2 = forall x y. (p1 :> p2) x y -> Maybe ((p2 :> p1) x y)
- selfCommuter :: Commute p => CommuteFn p p
- commuterIdFL :: CommuteFn p1 p2 -> CommuteFn p1 (FL p2)
- commuterFLId :: CommuteFn p1 p2 -> CommuteFn (FL p1) p2
- commuterIdRL :: CommuteFn p1 p2 -> CommuteFn p1 (RL p2)

# Documentation

genCommuteWhatWeCanRL :: (forall a b. (p :> p) a b -> Maybe ((p :> p) a b)) -> (RL p :> p) x y -> (RL p :> (p :> RL p)) x ySource

:: Commute p | |

=> (forall u v. p u v -> Bool) | predicate; if true we would like the patch in the left list |

-> FL p x y | input |

-> (FL p :> (FL p :> FL p)) x y |

split an `FL`

into left and right lists according to a predicate `p`

, using commutation as necessary.
If a patch does satisfy the predicate but cannot be commuted past one that does not satisfy
the predicate, it goes in the middle list; to sum up, we have: `all p left`

and `all (not.p) right`

, while
midddle is mixed.

simpleHeadPermutationsFL :: Commute p => FL p x y -> [FL p x y]Source

This is a minor variant of `headPermutationsFL`

with each permutation
is simply returned as a `FL`

headPermutationsRL :: Commute p => RL p x y -> [RL p x y]Source

`headPermutationsRL`

is like `headPermutationsFL`

, except that we
operate on an `RL`

(in other words, we are pushing things to the end of a
patch sequence instead of to the beginning).

headPermutationsFL :: Commute p => FL p x y -> [(p :> FL p) x y]Source

`headPermutationsFL`

`p:>:ps`

returns all the permutations of the list
in which one element of `ps`

is commuted past `p`

Suppose we have a sequence of patches

X h a y s-t-c k

Suppose furthermore that the patch `c`

depends on `t`

, which in turn
depends on `s`

. This function will return

X :> h a y s t c k h :> X a y s t c k a :> X h y s t c k y :> X h a s t c k s :> X h a y t c k k :> X h a y s t c

removeSubsequenceFL :: (MyEq p, Commute p) => FL p a b -> FL p a c -> Maybe (FL p b c)Source

`removeSubsequenceFL`

`ab abc`

returns `Just c'`

where all the patches in
`ab`

have been commuted out of it, if possible. If this is not possible
for any reason (the set of patches `ab`

is not actually a subset of `abc`

,
or they can't be commuted out) we return `Nothing`

.

removeSubsequenceRL :: (MyEq p, Commute p) => RL p ab abc -> RL p a abc -> Maybe (RL p a ab)Source

`removeSubsequenceRL`

is like `removeSubsequenceFL`

except that it works
on `RL`

partitionConflictingFL :: (Commute p1, Invert p1) => CommuteFn p1 p2 -> FL p1 x y -> p2 x z -> (FL p1 :> FL p1) x ySource

Partition a list into the patches that commute with the given patch and those that don't (including dependencies)

type CommuteFn p1 p2 = forall x y. (p1 :> p2) x y -> Maybe ((p2 :> p1) x y)Source

CommuteFn is the basis of a general framework for building up commutation operations between different patch types in a generic manner. Unfortunately type classes are not well suited to the problem because of the multiple possible routes by which the commuter for (FL p1, FL p2) can be built out of the commuter for (p1, p2) - and more complicated problems when we start building multiple constructors on top of each other. The type class resolution machinery really can't cope with selecting some route, because it doesn't know that all possible routes should be equivalent.

selfCommuter :: Commute p => CommuteFn p pSource

Build a commuter between a patch and itself using the operation from the type class.

commuterIdFL :: CommuteFn p1 p2 -> CommuteFn p1 (FL p2)Source

commuterFLId :: CommuteFn p1 p2 -> CommuteFn (FL p1) p2Source

commuterIdRL :: CommuteFn p1 p2 -> CommuteFn p1 (RL p2)Source