module Data.Functor.Couple (Twain(..), Couple(..)) where
import Data.Bifunctor
import Data.Functor.Product
import Data.Functor.Identity
import Data.Foldable
import Data.Traversable
import Data.Functor.Adjunction (unzipR)
import Data.Semigroup
import Data.Typeable
import Control.Applicative
import Control.Comonad
import Data.PairMonad ()
import Control.Lens (Wrapped(..), Rewrapped(..), iso)
newtype Twain b a = Twain { getTwain :: (b, a) }
deriving (Show, Functor, Traversable, Foldable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)
instance Wrapped (Twain b a) where
type Unwrapped (Twain b a) = (b, a)
_Wrapped' = iso getTwain Twain
instance Rewrapped (Twain c a) (Twain c b)
instance (Monoid b, Num a) => Num (Twain b a) where
(+) = liftA2 (+)
(*) = liftA2 (*)
() = liftA2 ()
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromInteger
instance (Monoid b, Fractional a) => Fractional (Twain b a) where
recip = fmap recip
fromRational = pure . fromRational
instance (Monoid b, Floating a) => Floating (Twain b a) where
pi = pure pi
sqrt = fmap sqrt
exp = fmap exp
log = fmap log
sin = fmap sin
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acos
instance (Monoid b, Enum a) => Enum (Twain b a) where
toEnum = pure . toEnum
fromEnum = fromEnum . extract
instance (Monoid b, Bounded a) => Bounded (Twain b a) where
minBound = pure minBound
maxBound = pure maxBound
instance Eq a => Eq (Twain b a) where
Twain (b,a) == Twain (b',a') = a == a'
instance Ord a => Ord (Twain b a) where
Twain (b,a) < Twain (b',a') = a < a'
instance (Monoid b, Real a, Enum a, Integral a) => Integral (Twain b a) where
quot = liftA2 quot
rem = liftA2 rem
quotRem = fmap (fmap unzipR) (liftA2 quotRem)
toInteger = toInteger . extract
instance (Monoid b, Real a) => Real (Twain b a) where
toRational = toRational . extract
instance (Monoid b, RealFrac a) => RealFrac (Twain b a) where
properFraction = first extract . unzipR . fmap properFraction
newtype Couple b a = Couple { getCouple :: (b, a) }
deriving (Show, Functor, Foldable, Traversable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)
instance Wrapped (Couple b a) where
type Unwrapped (Couple b a) = (b, a)
_Wrapped' = iso getCouple Couple
instance Rewrapped (Couple c a) (Couple c b)
instance (Monoid b, Num a) => Num (Couple b a) where
(+) = liftA2 (+)
(*) = liftA2 (*)
() = liftA2 ()
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromInteger
instance (Monoid b, Fractional a) => Fractional (Couple b a) where
recip = fmap recip
fromRational = pure . fromRational
instance (Monoid b, Floating a) => Floating (Couple b a) where
pi = pure pi
sqrt = fmap sqrt
exp = fmap exp
log = fmap log
sin = fmap sin
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acos
instance (Monoid b, Enum a) => Enum (Couple b a) where
toEnum = pure . toEnum
fromEnum = fromEnum . extract
instance (Monoid b, Bounded a) => Bounded (Couple b a) where
minBound = pure minBound
maxBound = pure maxBound
instance (Eq b, Eq a) => Eq (Couple b a) where
Couple ((b,a)) == Couple (b',a') = (b,a) == (b',a')
instance (Ord b, Ord a) => Ord (Couple b a) where
Couple (b,a) < Couple (b',a') = (b,a) < (b',a')
instance (Monoid b, Ord b, Real a, Enum a, Integral a) => Integral (Couple b a) where
quot = liftA2 quot
rem = liftA2 rem
quotRem = fmap (fmap unzipR) (liftA2 quotRem)
toInteger = toInteger . extract
instance (Monoid b, Ord b, Real a) => Real (Couple b a) where
toRational = toRational . extract
instance (Monoid b, Ord b, RealFrac a) => RealFrac (Couple b a) where
properFraction = first extract . unzipR . fmap properFraction