substituteSet :: Equations -> Maybe Equations
substituteSet equations =
    case findSubstitutionCandidate equations of
         Just equ@(TEVar v, t) -> do guard ((not . isCircular) equ)
                                     return $ S.insert equ (S.map (substituteEquation v t)
                                                           (S.delete equ equations))
         Nothing -> Just equations
         _ -> error "unexpected value from findSubstitutionCandidate"
    where substituteEquation :: Int -> TypeExpr -> Equation -> Equation
          substituteEquation v t'' (t,t') = ((substitute v t'' t),
                                             (substitute v t'' t'))
          isCircular :: Equation -> Bool
          isCircular (TEVar v, TEArrow t t') = (containsVar v t) || (containsVar v t')
          isCircular (TEArrow t t', TEVar v) = (containsVar v t) || (containsVar v t')
          isCircular _ = False

-- Five-steps step on the algorithm
--guard :: Bool -> Maybe ()
--guard True = Just ()
--guard False = Nothing
substituteSet :: Equations -> Maybe Equations
substituteSet equations =
    case findSubstitutionCandidate equations of
         Just equ@(TEVar v, t) -> do guard ((not . isCircular) equ)
                                     return $ S.insert equ (S.map (substituteEquation v t)
                                                           (S.delete equ equations))
         Nothing -> Just equations
         _ -> error "unexpected value from findSubstitutionCandidate"
    where substituteEquation :: Int -> TypeExpr -> Equation -> Equation
          substituteEquation v t'' (t,t') = ((substitute v t'' t),
                                             (substitute v t'' t'))
          isCircular :: Equation -> Bool
          isCircular (TEVar v, TEArrow t t') = (containsVar v t) || (containsVar v t')
          isCircular (TEArrow t t', TEVar v) = (containsVar v t) || (containsVar v t')
          isCircular _ = False

-- Five-steps step on the algorithm
--guard :: Bool -> Maybe ()
--guard True = Just ()
--guard False = Nothing
substituteSet equations =
    case findSubstitutionCandidate equations of
         Just equ@(TEVar v, t) -> do guard ((not . isCircular) equ)
                                     return $ S.insert equ (S.map (substituteEquation v t)
                                                           (S.delete equ equations))
         Nothing -> Just equations
         _ -> error "unexpected value from findSubstitutionCandidate"
    where substituteEquation :: Int -> TypeExpr -> Equation -> Equation
          substituteEquation v t'' (t,t') = ((substitute v t'' t),
                                             (substitute v t'' t'))
          isCircular :: Equation -> Bool
          isCircular (TEVar v, TEArrow t t') = (containsVar v t) || (containsVar v t')
          isCircular (TEArrow t t', TEVar v) = (containsVar v t) || (containsVar v t')
          isCircular _ = False

-- Five-steps step on the algorithm
--guard :: Bool -> Maybe ()
--guard True = Just ()
--guard False = Nothing