calculateCoincidenceHeight :: CoincidenceSubscribed a -> IO Int
calculateCoincidenceHeight subscribed = do
  outerHeight <- readIORef $ eventSubscribedHeightRef $ coincidenceSubscribedOuterParent subscribed
  innerHeight <- maybe (return 0) (readIORef . eventSubscribedHeightRef) =<< readIORef (coincidenceSubscribedInnerParent subscribed)
  return $ if outerHeight == invalidHeight || innerHeight == invalidHeight then invalidHeight else max outerHeight innerHeight

{-
recalculateEventSubscribedHeight :: EventSubscribed a -> IO Int
recalculateEventSubscribedHeight es = case es of
  EventSubscribedRoot _ -> return 0
  EventSubscribedNever -> return 0
  EventSubscribedPush subscribed -> recalculateEventSubscribedHeight $ pushSubscribedParent subscribed
  EventSubscribedMerge subscribed -> do
    oldHeight <- readIORef $ mergeSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateMergeHeight subscribed
      writeIORef (mergeSubscribedHeight subscribed) height
      return height
  EventSubscribedFan _ subscribed -> recalculateEventSubscribedHeight $ fanSubscribedParent subscribed
  EventSubscribedSwitch subscribed -> do
    oldHeight <- readIORef $ switchSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateSwitchHeight subscribed
      writeIORef (switchSubscribedHeight subscribed) height
      return height
  EventSubscribedCoincidence subscribed -> recalculateCoincidenceHeight subscribed
-}
calculateCoincidenceHeight :: CoincidenceSubscribed a -> IO Int
calculateCoincidenceHeight subscribed = do
  outerHeight <- readIORef $ eventSubscribedHeightRef $ coincidenceSubscribedOuterParent subscribed
  innerHeight <- maybe (return 0) (readIORef . eventSubscribedHeightRef) =<< readIORef (coincidenceSubscribedInnerParent subscribed)
  return $ if outerHeight == invalidHeight || innerHeight == invalidHeight then invalidHeight else max outerHeight innerHeight

{-
recalculateEventSubscribedHeight :: EventSubscribed a -> IO Int
recalculateEventSubscribedHeight es = case es of
  EventSubscribedRoot _ -> return 0
  EventSubscribedNever -> return 0
  EventSubscribedPush subscribed -> recalculateEventSubscribedHeight $ pushSubscribedParent subscribed
  EventSubscribedMerge subscribed -> do
    oldHeight <- readIORef $ mergeSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateMergeHeight subscribed
      writeIORef (mergeSubscribedHeight subscribed) height
      return height
  EventSubscribedFan _ subscribed -> recalculateEventSubscribedHeight $ fanSubscribedParent subscribed
  EventSubscribedSwitch subscribed -> do
    oldHeight <- readIORef $ switchSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateSwitchHeight subscribed
      writeIORef (switchSubscribedHeight subscribed) height
      return height
  EventSubscribedCoincidence subscribed -> recalculateCoincidenceHeight subscribed
-}
calculateCoincidenceHeight subscribed = do
  outerHeight <- readIORef $ eventSubscribedHeightRef $ coincidenceSubscribedOuterParent subscribed
  innerHeight <- maybe (return 0) (readIORef . eventSubscribedHeightRef) =<< readIORef (coincidenceSubscribedInnerParent subscribed)
  return $ if outerHeight == invalidHeight || innerHeight == invalidHeight then invalidHeight else max outerHeight innerHeight

{-
recalculateEventSubscribedHeight :: EventSubscribed a -> IO Int
recalculateEventSubscribedHeight es = case es of
  EventSubscribedRoot _ -> return 0
  EventSubscribedNever -> return 0
  EventSubscribedPush subscribed -> recalculateEventSubscribedHeight $ pushSubscribedParent subscribed
  EventSubscribedMerge subscribed -> do
    oldHeight <- readIORef $ mergeSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateMergeHeight subscribed
      writeIORef (mergeSubscribedHeight subscribed) height
      return height
  EventSubscribedFan _ subscribed -> recalculateEventSubscribedHeight $ fanSubscribedParent subscribed
  EventSubscribedSwitch subscribed -> do
    oldHeight <- readIORef $ switchSubscribedHeight subscribed
    if oldHeight /= invalidHeight then return oldHeight else do
      height <- calculateSwitchHeight subscribed
      writeIORef (switchSubscribedHeight subscribed) height
      return height
  EventSubscribedCoincidence subscribed -> recalculateCoincidenceHeight subscribed
-}