module DFAMin (minimizeDFA) where
import AbsSyn
import Control.Monad (guard)
import Data.Bifunctor (second)
import Data.IntMap (IntMap)
import Data.IntSet (IntSet)
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import qualified Data.List as List
import qualified Data.Map as Map
type OldSNum = Int
type NewSNum = Int
minimizeDFA :: forall a. Ord a => DFA OldSNum a -> DFA NewSNum a
minimizeDFA :: forall a. Ord a => DFA OldSNum a -> DFA OldSNum a
minimizeDFA dfa :: DFA OldSNum a
dfa@(DFA [OldSNum]
starts Map OldSNum (State OldSNum a)
statemap) = [OldSNum] -> Map OldSNum (State OldSNum a) -> DFA OldSNum a
forall s a. [s] -> Map s (State s a) -> DFA s a
DFA [OldSNum]
starts (Map OldSNum (State OldSNum a) -> DFA OldSNum a)
-> Map OldSNum (State OldSNum a) -> DFA OldSNum a
forall a b. (a -> b) -> a -> b
$ [(OldSNum, State OldSNum a)] -> Map OldSNum (State OldSNum a)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(OldSNum, State OldSNum a)]
new_states
where
equiv_classes :: [EquivalenceClass]
equiv_classes :: [EquivalenceClass]
equiv_classes = DFA OldSNum a -> [EquivalenceClass]
forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
groupEquivalentStates DFA OldSNum a
dfa
numbered_states :: [(NewSNum, EquivalenceClass)]
numbered_states :: [(OldSNum, EquivalenceClass)]
numbered_states = OldSNum
-> [OldSNum] -> [EquivalenceClass] -> [(OldSNum, EquivalenceClass)]
number ([OldSNum] -> OldSNum
forall a. [a] -> OldSNum
forall (t :: * -> *) a. Foldable t => t a -> OldSNum
length [OldSNum]
starts) [OldSNum]
starts [EquivalenceClass]
equiv_classes
number :: NewSNum -> [NewSNum] -> [EquivalenceClass] -> [(NewSNum, EquivalenceClass)]
number :: OldSNum
-> [OldSNum] -> [EquivalenceClass] -> [(OldSNum, EquivalenceClass)]
number OldSNum
_ [OldSNum]
_ [] = []
number OldSNum
n [OldSNum]
unassigned_starts (EquivalenceClass
ss:[EquivalenceClass]
sss)
| [OldSNum] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [OldSNum]
starts_ss = (OldSNum
n,EquivalenceClass
ss) (OldSNum, EquivalenceClass)
-> [(OldSNum, EquivalenceClass)] -> [(OldSNum, EquivalenceClass)]
forall a. a -> [a] -> [a]
: OldSNum -> [(OldSNum, EquivalenceClass)]
continue (OldSNum
nOldSNum -> OldSNum -> OldSNum
forall a. Num a => a -> a -> a
+OldSNum
1)
| Bool
otherwise = (OldSNum -> (OldSNum, EquivalenceClass))
-> [OldSNum] -> [(OldSNum, EquivalenceClass)]
forall a b. (a -> b) -> [a] -> [b]
map (,EquivalenceClass
ss) [OldSNum]
starts_ss [(OldSNum, EquivalenceClass)]
-> [(OldSNum, EquivalenceClass)] -> [(OldSNum, EquivalenceClass)]
forall a. [a] -> [a] -> [a]
++ OldSNum -> [(OldSNum, EquivalenceClass)]
continue OldSNum
n
where
([OldSNum]
starts_ss, [OldSNum]
starts_other) = (OldSNum -> Bool) -> [OldSNum] -> ([OldSNum], [OldSNum])
forall a. (a -> Bool) -> [a] -> ([a], [a])
List.partition (OldSNum -> EquivalenceClass -> Bool
`IntSet.member` EquivalenceClass
ss) [OldSNum]
unassigned_starts
continue :: OldSNum -> [(OldSNum, EquivalenceClass)]
continue OldSNum
n' = OldSNum
-> [OldSNum] -> [EquivalenceClass] -> [(OldSNum, EquivalenceClass)]
number OldSNum
n' [OldSNum]
starts_other [EquivalenceClass]
sss
new_states :: [(NewSNum, State NewSNum a)]
new_states :: [(OldSNum, State OldSNum a)]
new_states = ((OldSNum, EquivalenceClass) -> (OldSNum, State OldSNum a))
-> [(OldSNum, EquivalenceClass)] -> [(OldSNum, State OldSNum a)]
forall a b. (a -> b) -> [a] -> [b]
map ((EquivalenceClass -> State OldSNum a)
-> (OldSNum, EquivalenceClass) -> (OldSNum, State OldSNum a)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second EquivalenceClass -> State OldSNum a
class_to_new_state) [(OldSNum, EquivalenceClass)]
numbered_states
class_to_new_state :: EquivalenceClass -> State NewSNum a
class_to_new_state :: EquivalenceClass -> State OldSNum a
class_to_new_state =
State OldSNum a -> State OldSNum a
old_state_to_new_state (State OldSNum a -> State OldSNum a)
-> (EquivalenceClass -> State OldSNum a)
-> EquivalenceClass
-> State OldSNum a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map OldSNum (State OldSNum a) -> OldSNum -> State OldSNum a
forall {c}. Map OldSNum c -> OldSNum -> c
lookupOrPanic Map OldSNum (State OldSNum a)
statemap (OldSNum -> State OldSNum a)
-> (EquivalenceClass -> OldSNum)
-> EquivalenceClass
-> State OldSNum a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EquivalenceClass -> OldSNum
IntSet.findMin
where
lookupOrPanic :: Map OldSNum c -> OldSNum -> c
lookupOrPanic = (OldSNum -> Map OldSNum c -> c) -> Map OldSNum c -> OldSNum -> c
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((OldSNum -> Map OldSNum c -> c) -> Map OldSNum c -> OldSNum -> c)
-> (OldSNum -> Map OldSNum c -> c) -> Map OldSNum c -> OldSNum -> c
forall a b. (a -> b) -> a -> b
$ c -> OldSNum -> Map OldSNum c -> c
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault c
forall {a}. a
panic
panic :: a
panic = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"alex::DFAMin.minimizeDFA: panic: state not found"
old_state_to_new_state :: State OldSNum a -> State NewSNum a
old_state_to_new_state :: State OldSNum a -> State OldSNum a
old_state_to_new_state (State [Accept a]
old_accepts IntMap OldSNum
old_transitions) =
[Accept a] -> IntMap OldSNum -> State OldSNum a
forall s a. [Accept a] -> IntMap s -> State s a
State ((Accept a -> Accept a) -> [Accept a] -> [Accept a]
forall a b. (a -> b) -> [a] -> [b]
map Accept a -> Accept a
fix_acc [Accept a]
old_accepts) ((OldSNum -> OldSNum) -> IntMap OldSNum -> IntMap OldSNum
forall a b. (a -> b) -> IntMap a -> IntMap b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap OldSNum -> OldSNum
get_new IntMap OldSNum
old_transitions)
fix_acc :: Accept a -> Accept a
fix_acc :: Accept a -> Accept a
fix_acc Accept a
acc = Accept a
acc { accRightCtx :: RightContext OldSNum
accRightCtx = (OldSNum -> OldSNum)
-> RightContext OldSNum -> RightContext OldSNum
forall a b. (a -> b) -> RightContext a -> RightContext b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap OldSNum -> OldSNum
get_new (RightContext OldSNum -> RightContext OldSNum)
-> RightContext OldSNum -> RightContext OldSNum
forall a b. (a -> b) -> a -> b
$ Accept a -> RightContext OldSNum
forall a. Accept a -> RightContext OldSNum
accRightCtx Accept a
acc }
get_new :: OldSNum -> NewSNum
get_new :: OldSNum -> OldSNum
get_new OldSNum
k = OldSNum -> OldSNum -> IntMap OldSNum -> OldSNum
forall a. a -> OldSNum -> IntMap a -> a
IntMap.findWithDefault OldSNum
forall {a}. a
panic OldSNum
k IntMap OldSNum
old_to_new
where
panic :: a
panic = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"alex::DFAMin.minimizeDFA: panic: state not found"
old_to_new :: IntMap NewSNum
old_to_new :: IntMap OldSNum
old_to_new = [(OldSNum, OldSNum)] -> IntMap OldSNum
forall a. [(OldSNum, a)] -> IntMap a
IntMap.fromList ([(OldSNum, OldSNum)] -> IntMap OldSNum)
-> [(OldSNum, OldSNum)] -> IntMap OldSNum
forall a b. (a -> b) -> a -> b
$ do
(OldSNum
n,EquivalenceClass
ss) <- [(OldSNum, EquivalenceClass)]
numbered_states
OldSNum
s <- EquivalenceClass -> [OldSNum]
IntSet.toList EquivalenceClass
ss
(OldSNum, OldSNum) -> [(OldSNum, OldSNum)]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OldSNum
s,OldSNum
n)
type EquivalenceClass = IntSet
initialSubsets :: forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
initialSubsets :: forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
initialSubsets DFA OldSNum a
dfa = Map [Accept a] EquivalenceClass -> [EquivalenceClass]
forall k a. Map k a -> [a]
Map.elems (Map [Accept a] EquivalenceClass -> [EquivalenceClass])
-> Map [Accept a] EquivalenceClass -> [EquivalenceClass]
forall a b. (a -> b) -> a -> b
$ (EquivalenceClass -> EquivalenceClass -> EquivalenceClass)
-> [([Accept a], EquivalenceClass)]
-> Map [Accept a] EquivalenceClass
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith EquivalenceClass -> EquivalenceClass -> EquivalenceClass
IntSet.union ([([Accept a], EquivalenceClass)]
-> Map [Accept a] EquivalenceClass)
-> [([Accept a], EquivalenceClass)]
-> Map [Accept a] EquivalenceClass
forall a b. (a -> b) -> a -> b
$ do
(OldSNum
stateIndex, State [Accept a]
accepts IntMap OldSNum
_transitions) <- Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)])
-> Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)]
forall a b. (a -> b) -> a -> b
$ DFA OldSNum a -> Map OldSNum (State OldSNum a)
forall s a. DFA s a -> Map s (State s a)
dfa_states DFA OldSNum a
dfa
([Accept a], EquivalenceClass) -> [([Accept a], EquivalenceClass)]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Accept a]
accepts, OldSNum -> EquivalenceClass
IntSet.singleton OldSNum
stateIndex)
generateReverseTransitionCache :: forall a. Ord a => DFA OldSNum a -> [IntMap EquivalenceClass]
generateReverseTransitionCache :: forall a. Ord a => DFA OldSNum a -> [IntMap EquivalenceClass]
generateReverseTransitionCache DFA OldSNum a
dfa = IntMap (IntMap EquivalenceClass) -> [IntMap EquivalenceClass]
forall a. IntMap a -> [a]
IntMap.elems (IntMap (IntMap EquivalenceClass) -> [IntMap EquivalenceClass])
-> IntMap (IntMap EquivalenceClass) -> [IntMap EquivalenceClass]
forall a b. (a -> b) -> a -> b
$
(IntMap EquivalenceClass
-> IntMap EquivalenceClass -> IntMap EquivalenceClass)
-> [(OldSNum, IntMap EquivalenceClass)]
-> IntMap (IntMap EquivalenceClass)
forall a. (a -> a -> a) -> [(OldSNum, a)] -> IntMap a
IntMap.fromListWith ((EquivalenceClass -> EquivalenceClass -> EquivalenceClass)
-> IntMap EquivalenceClass
-> IntMap EquivalenceClass
-> IntMap EquivalenceClass
forall a. (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a
IntMap.unionWith EquivalenceClass -> EquivalenceClass -> EquivalenceClass
IntSet.union) ([(OldSNum, IntMap EquivalenceClass)]
-> IntMap (IntMap EquivalenceClass))
-> [(OldSNum, IntMap EquivalenceClass)]
-> IntMap (IntMap EquivalenceClass)
forall a b. (a -> b) -> a -> b
$ do
(OldSNum
sourceState, State [Accept a]
_accepts IntMap OldSNum
transitions) <- Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)])
-> Map OldSNum (State OldSNum a) -> [(OldSNum, State OldSNum a)]
forall a b. (a -> b) -> a -> b
$ DFA OldSNum a -> Map OldSNum (State OldSNum a)
forall s a. DFA s a -> Map s (State s a)
dfa_states DFA OldSNum a
dfa
(OldSNum
token, OldSNum
targetState) <- IntMap OldSNum -> [(OldSNum, OldSNum)]
forall a. IntMap a -> [(OldSNum, a)]
IntMap.toList IntMap OldSNum
transitions
(OldSNum, IntMap EquivalenceClass)
-> [(OldSNum, IntMap EquivalenceClass)]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OldSNum
token, OldSNum -> EquivalenceClass -> IntMap EquivalenceClass
forall a. OldSNum -> a -> IntMap a
IntMap.singleton OldSNum
targetState (OldSNum -> EquivalenceClass
IntSet.singleton OldSNum
sourceState))
refine
:: EquivalenceClass
-> EquivalenceClass
-> Maybe (EquivalenceClass, EquivalenceClass)
refine :: EquivalenceClass
-> EquivalenceClass -> Maybe (EquivalenceClass, EquivalenceClass)
refine EquivalenceClass
x EquivalenceClass
y =
if EquivalenceClass -> Bool
IntSet.null EquivalenceClass
intersection Bool -> Bool -> Bool
|| EquivalenceClass -> Bool
IntSet.null EquivalenceClass
difference
then Maybe (EquivalenceClass, EquivalenceClass)
forall a. Maybe a
Nothing
else (EquivalenceClass, EquivalenceClass)
-> Maybe (EquivalenceClass, EquivalenceClass)
forall a. a -> Maybe a
Just (EquivalenceClass
intersection, EquivalenceClass
difference)
where
intersection :: EquivalenceClass
intersection = EquivalenceClass -> EquivalenceClass -> EquivalenceClass
IntSet.intersection EquivalenceClass
y EquivalenceClass
x
difference :: EquivalenceClass
difference = EquivalenceClass -> EquivalenceClass -> EquivalenceClass
IntSet.difference EquivalenceClass
y EquivalenceClass
x
groupEquivalentStates :: forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
groupEquivalentStates :: forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
groupEquivalentStates DFA OldSNum a
dfa = ([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass]
outerLoop ([], DFA OldSNum a -> [EquivalenceClass]
forall a. Ord a => DFA OldSNum a -> [EquivalenceClass]
initialSubsets DFA OldSNum a
dfa)
where
reverseTransitionCache :: [IntMap EquivalenceClass]
reverseTransitionCache :: [IntMap EquivalenceClass]
reverseTransitionCache = DFA OldSNum a -> [IntMap EquivalenceClass]
forall a. Ord a => DFA OldSNum a -> [IntMap EquivalenceClass]
generateReverseTransitionCache DFA OldSNum a
dfa
outerLoop :: ([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass]
outerLoop :: ([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass]
outerLoop ([EquivalenceClass]
r, []) = [EquivalenceClass]
r
outerLoop ([EquivalenceClass]
r, EquivalenceClass
a:[EquivalenceClass]
w) = ([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass]
outerLoop (([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass])
-> ([EquivalenceClass], [EquivalenceClass]) -> [EquivalenceClass]
forall a b. (a -> b) -> a -> b
$ (([EquivalenceClass], [EquivalenceClass])
-> EquivalenceClass -> ([EquivalenceClass], [EquivalenceClass]))
-> ([EquivalenceClass], [EquivalenceClass])
-> [EquivalenceClass]
-> ([EquivalenceClass], [EquivalenceClass])
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ([EquivalenceClass], [EquivalenceClass])
-> EquivalenceClass -> ([EquivalenceClass], [EquivalenceClass])
forall {t :: * -> *} {t :: * -> *}.
(Foldable t, Foldable t) =>
(t EquivalenceClass, t EquivalenceClass)
-> EquivalenceClass -> ([EquivalenceClass], [EquivalenceClass])
refineWithX (EquivalenceClass
aEquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
r,[EquivalenceClass]
w) ([EquivalenceClass] -> ([EquivalenceClass], [EquivalenceClass]))
-> [EquivalenceClass] -> ([EquivalenceClass], [EquivalenceClass])
forall a b. (a -> b) -> a -> b
$ do
IntMap EquivalenceClass
allPreviousStates <- [IntMap EquivalenceClass]
reverseTransitionCache
let x :: EquivalenceClass
x = [EquivalenceClass] -> EquivalenceClass
forall (f :: * -> *).
Foldable f =>
f EquivalenceClass -> EquivalenceClass
IntSet.unions ([EquivalenceClass] -> EquivalenceClass)
-> [EquivalenceClass] -> EquivalenceClass
forall a b. (a -> b) -> a -> b
$ do
(OldSNum
target, EquivalenceClass
sources) <- IntMap EquivalenceClass -> [(OldSNum, EquivalenceClass)]
forall a. IntMap a -> [(OldSNum, a)]
IntMap.toList IntMap EquivalenceClass
allPreviousStates
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> [()]) -> Bool -> [()]
forall a b. (a -> b) -> a -> b
$ OldSNum
target OldSNum -> EquivalenceClass -> Bool
`IntSet.member` EquivalenceClass
a
EquivalenceClass -> [EquivalenceClass]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure EquivalenceClass
sources
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> [()]) -> Bool -> [()]
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ EquivalenceClass -> Bool
IntSet.null EquivalenceClass
x
EquivalenceClass -> [EquivalenceClass]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure EquivalenceClass
x
refineWithX :: (t EquivalenceClass, t EquivalenceClass)
-> EquivalenceClass -> ([EquivalenceClass], [EquivalenceClass])
refineWithX (t EquivalenceClass
r, t EquivalenceClass
w) EquivalenceClass
x =
let ([EquivalenceClass]
r', [EquivalenceClass]
w') = (([EquivalenceClass], [EquivalenceClass])
-> EquivalenceClass -> ([EquivalenceClass], [EquivalenceClass]))
-> ([EquivalenceClass], [EquivalenceClass])
-> t EquivalenceClass
-> ([EquivalenceClass], [EquivalenceClass])
forall b a. (b -> a -> b) -> b -> t a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (EquivalenceClass
-> ([EquivalenceClass], [EquivalenceClass])
-> EquivalenceClass
-> ([EquivalenceClass], [EquivalenceClass])
processR EquivalenceClass
x) ([], []) t EquivalenceClass
r
in ([EquivalenceClass]
r', ([EquivalenceClass] -> EquivalenceClass -> [EquivalenceClass])
-> [EquivalenceClass] -> t EquivalenceClass -> [EquivalenceClass]
forall b a. (b -> a -> b) -> b -> t a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (EquivalenceClass
-> [EquivalenceClass] -> EquivalenceClass -> [EquivalenceClass]
processW EquivalenceClass
x) [EquivalenceClass]
w' t EquivalenceClass
w)
processR :: EquivalenceClass
-> ([EquivalenceClass], [EquivalenceClass])
-> EquivalenceClass
-> ([EquivalenceClass], [EquivalenceClass])
processR EquivalenceClass
x ([EquivalenceClass]
r', [EquivalenceClass]
w') EquivalenceClass
y = case EquivalenceClass
-> EquivalenceClass -> Maybe (EquivalenceClass, EquivalenceClass)
refine EquivalenceClass
x EquivalenceClass
y of
Maybe (EquivalenceClass, EquivalenceClass)
Nothing -> (EquivalenceClass
yEquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
r', [EquivalenceClass]
w')
Just (EquivalenceClass
y1, EquivalenceClass
y2)
| EquivalenceClass -> OldSNum
IntSet.size EquivalenceClass
y1 OldSNum -> OldSNum -> Bool
forall a. Ord a => a -> a -> Bool
<= EquivalenceClass -> OldSNum
IntSet.size EquivalenceClass
y2 -> (EquivalenceClass
y2EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
r', EquivalenceClass
y1EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
w')
| Bool
otherwise -> (EquivalenceClass
y1EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
r', EquivalenceClass
y2EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
w')
processW :: EquivalenceClass
-> [EquivalenceClass] -> EquivalenceClass -> [EquivalenceClass]
processW EquivalenceClass
x [EquivalenceClass]
w' EquivalenceClass
y = case EquivalenceClass
-> EquivalenceClass -> Maybe (EquivalenceClass, EquivalenceClass)
refine EquivalenceClass
x EquivalenceClass
y of
Maybe (EquivalenceClass, EquivalenceClass)
Nothing -> EquivalenceClass
yEquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
w'
Just (EquivalenceClass
y1, EquivalenceClass
y2) -> EquivalenceClass
y1EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:EquivalenceClass
y2EquivalenceClass -> [EquivalenceClass] -> [EquivalenceClass]
forall a. a -> [a] -> [a]
:[EquivalenceClass]
w'