reachableFromQVar :: QVar -> Reachability
reachableFromQVar qa =
  reachableUnions [immediate, lowerBound]
  where
    immediate = do
      cs <- ask
      tqs <- ListT $ return $ csQuery cs $ QueryTQualSetByQVarUpperBound qa
      guard $ TMut `Set.member` tqs
      return qa
    lowerBound = do
      cs <- ask
      t <- ListT $ return $ csQuery cs $ QueryTypeByQVarUpperBound qa
      reachableFromType t
reachableFromQVar :: QVar -> Reachability
reachableFromQVar qa =
  reachableUnions [immediate, lowerBound]
  where
    immediate = do
      cs <- ask
      tqs <- ListT $ return $ csQuery cs $ QueryTQualSetByQVarUpperBound qa
      guard $ TMut `Set.member` tqs
      return qa
    lowerBound = do
      cs <- ask
      t <- ListT $ return $ csQuery cs $ QueryTypeByQVarUpperBound qa
      reachableFromType t
reachableFromQVar qa =
  reachableUnions [immediate, lowerBound]
  where
    immediate = do
      cs <- ask
      tqs <- ListT $ return $ csQuery cs $ QueryTQualSetByQVarUpperBound qa
      guard $ TMut `Set.member` tqs
      return qa
    lowerBound = do
      cs <- ask
      t <- ListT $ return $ csQuery cs $ QueryTypeByQVarUpperBound qa
      reachableFromType t