hasTerminatingPath :: forall sym sta. (Ord sym, Ord sta) => Set sym -> Fa sym sta -> Bool
hasTerminatingPath symbols fa =
  not (null $ finalStates fa) && hasTerminatingPath' Set.empty (initialStates fa)
    where
      hasTerminatingPath' :: Set sta -> Set sta -> Bool
      hasTerminatingPath' processed next
        | null next = False
        | not $ null $ next `Set.intersection` finalStates fa = True
        | otherwise =
          let
            processed' = processed `Set.union` next
            next' = newStates symbols fa next Set.\\ processed'
          in
            hasTerminatingPath' processed' next'

      newStates :: Set sym -> Fa sym sta -> Set sta -> Set sta
      newStates symbols fa states =
        Helpers.unions $ postForEachSymbol fa states symbols

-- |Checks whether the first FA is subset of the second FA using the naive algorithm.
hasTerminatingPath :: forall sym sta. (Ord sym, Ord sta) => Set sym -> Fa sym sta -> Bool
hasTerminatingPath symbols fa =
  not (null $ finalStates fa) && hasTerminatingPath' Set.empty (initialStates fa)
    where
      hasTerminatingPath' :: Set sta -> Set sta -> Bool
      hasTerminatingPath' processed next
        | null next = False
        | not $ null $ next `Set.intersection` finalStates fa = True
        | otherwise =
          let
            processed' = processed `Set.union` next
            next' = newStates symbols fa next Set.\\ processed'
          in
            hasTerminatingPath' processed' next'

      newStates :: Set sym -> Fa sym sta -> Set sta -> Set sta
      newStates symbols fa states =
        Helpers.unions $ postForEachSymbol fa states symbols

-- |Checks whether the first FA is subset of the second FA using the naive algorithm.
hasTerminatingPath symbols fa =
  not (null $ finalStates fa) && hasTerminatingPath' Set.empty (initialStates fa)
    where
      hasTerminatingPath' :: Set sta -> Set sta -> Bool
      hasTerminatingPath' processed next
        | null next = False
        | not $ null $ next `Set.intersection` finalStates fa = True
        | otherwise =
          let
            processed' = processed `Set.union` next
            next' = newStates symbols fa next Set.\\ processed'
          in
            hasTerminatingPath' processed' next'

      newStates :: Set sym -> Fa sym sta -> Set sta -> Set sta
      newStates symbols fa states =
        Helpers.unions $ postForEachSymbol fa states symbols

-- |Checks whether the first FA is subset of the second FA using the naive algorithm.