-- |Creates an intersection of two FAs.
intersect :: (Ord sym, Ord sta1, Ord sta2) => Set sym -> Fa sym sta1 -> Fa sym sta2 -> Fa sym (sta1, sta2)
intersect symbols (Fa initialStates1 finalStates1 transitions1) (Fa initialStates2 finalStates2 transitions2) =
  let
    transitions =
      symbols `andThen` (\symbol ->
      transitions1 `andThen` (\(Transition symbol1 source1 target1) ->
      transitions2 `andThen` (\(Transition symbol2 source2 target2) ->
      guard (symbol1 == symbol && symbol2 == symbol) `andThen` (\_ ->
      Helpers.return $ Transition symbol (source1, source2) (target1, target2)))))
  in
    Fa
      (initialStates1 `andThen` (\initial1 -> initialStates2 `andThen` (\initial2 -> Helpers.return (initial1, initial2))))
      (finalStates1 `andThen` (\final1 -> finalStates2 `andThen` (\final2 -> Helpers.return (final1, final2))))
      transitions
intersect :: (Ord sym, Ord sta1, Ord sta2) => Set sym -> Fa sym sta1 -> Fa sym sta2 -> Fa sym (sta1, sta2)
intersect symbols (Fa initialStates1 finalStates1 transitions1) (Fa initialStates2 finalStates2 transitions2) =
  let
    transitions =
      symbols `andThen` (\symbol ->
      transitions1 `andThen` (\(Transition symbol1 source1 target1) ->
      transitions2 `andThen` (\(Transition symbol2 source2 target2) ->
      guard (symbol1 == symbol && symbol2 == symbol) `andThen` (\_ ->
      Helpers.return $ Transition symbol (source1, source2) (target1, target2)))))
  in
    Fa
      (initialStates1 `andThen` (\initial1 -> initialStates2 `andThen` (\initial2 -> Helpers.return (initial1, initial2))))
      (finalStates1 `andThen` (\final1 -> finalStates2 `andThen` (\final2 -> Helpers.return (final1, final2))))
      transitions
intersect symbols (Fa initialStates1 finalStates1 transitions1) (Fa initialStates2 finalStates2 transitions2) =
  let
    transitions =
      symbols `andThen` (\symbol ->
      transitions1 `andThen` (\(Transition symbol1 source1 target1) ->
      transitions2 `andThen` (\(Transition symbol2 source2 target2) ->
      guard (symbol1 == symbol && symbol2 == symbol) `andThen` (\_ ->
      Helpers.return $ Transition symbol (source1, source2) (target1, target2)))))
  in
    Fa
      (initialStates1 `andThen` (\initial1 -> initialStates2 `andThen` (\initial2 -> Helpers.return (initial1, initial2))))
      (finalStates1 `andThen` (\final1 -> finalStates2 `andThen` (\final2 -> Helpers.return (final1, final2))))
      transitions