module Fx.Transform
where

import Fx.Prelude
import Fx.EitherEffect.Types


{-|
Natural transformation.
An abstraction over the transformation of kind-2 @input@ to @output@, both producing the same @result@.
-}
newtype input --> output =
  Transform (forall result. input result -> output result)

{-|
Given a natural transformation of the left monad and a natural transformation of the right monad,
produces a natural transformation of either of them.
-}
eitherEffect :: Monad either => (left --> either) -> (right --> either) -> (EitherEffect left right either --> either)
eitherEffect (Transform leftTrans) (Transform rightTrans) =
  Transform (\ (EitherEffect context) -> context leftTrans rightTrans)

instance Category (-->) where
  id = Transform id
  (.) (Transform left) (Transform right) = Transform (left . right)