module Control.Functor
    ( module Control.Category
    , Functor (..)
    , map
    , for
    , (<$)
    ) where

import GHC.IOBase

import Control.Category
import Data.Function

{- |
The 'Functor' class is used for types that can be mapped
over. Instances of 'Functor' should satisfy the following laws:

> fmap id  ==  id
> fmap (f . g)  ==  fmap f . fmap g
-}

infixl 4 $>
class Category (~>) => Functor (~>) f where
    ($>) :: (a ~> b) -> (f a ~> f b)

{-# RULES
"identity" map id = id
"distribution" forall f g .
                 map f . map g = map (f . g)
 #-}

map :: Functor (~>) f => (a ~> b) -> (f a ~> f b)
map = ($>)

for :: Functor Hask f => f a -> (a -> b) -> f b
for = flip map

infixl 4 <$
(<$) :: Functor Hask f => f (a -> b) -> (a -> f b)
f <$ x = applyTo x $> f

instance Functor Hask (Hask a) where
    ($>) = (.)

instance Functor Hask IO where
    f $> x = bindIO x $ returnIO . f
