semiLatticeOfOMNodeType :: OMNodeType -> OMNodeType -> OMNodeType
semiLatticeOfOMNodeType a b = case go a b of
  TopType -> case go b a of
    TopType -> TopType
    c -> c
  c       -> c
  where
    go :: OMNodeType -> OMNodeType -> OMNodeType
    go a b | a == b = a
    go (ElemType ea) (ElemType eb) = subFix (ElemType ea /\ ElemType eb :: ElementalType)
    go a@(ElemType _) b@(GridType v c) = let d = a /\ c in
           if d==TopType then TopType else GridType v d
    go (GridType v1 c1) (GridType v2 c2) = (if v1 == v2 then GridType v1 (c1 /\ c2) else TopType)
    go _ _          = TopType
semiLatticeOfOMNodeType :: OMNodeType -> OMNodeType -> OMNodeType
semiLatticeOfOMNodeType a b = case go a b of
  TopType -> case go b a of
    TopType -> TopType
    c -> c
  c       -> c
  where
    go :: OMNodeType -> OMNodeType -> OMNodeType
    go a b | a == b = a
    go (ElemType ea) (ElemType eb) = subFix (ElemType ea /\ ElemType eb :: ElementalType)
    go a@(ElemType _) b@(GridType v c) = let d = a /\ c in
           if d==TopType then TopType else GridType v d
    go (GridType v1 c1) (GridType v2 c2) = (if v1 == v2 then GridType v1 (c1 /\ c2) else TopType)
    go _ _          = TopType
semiLatticeOfOMNodeType a b = case go a b of
  TopType -> case go b a of
    TopType -> TopType
    c -> c
  c       -> c
  where
    go :: OMNodeType -> OMNodeType -> OMNodeType
    go a b | a == b = a
    go (ElemType ea) (ElemType eb) = subFix (ElemType ea /\ ElemType eb :: ElementalType)
    go a@(ElemType _) b@(GridType v c) = let d = a /\ c in
           if d==TopType then TopType else GridType v d
    go (GridType v1 c1) (GridType v2 c2) = (if v1 == v2 then GridType v1 (c1 /\ c2) else TopType)
    go _ _          = TopType