{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeOperators #-}
module Data.Vinyl.Functor
(
Identity(..)
, Thunk(..)
, Lift(..)
, ElField(..)
, Compose(..)
, (:.)
, Const(..)
) where
import Data.Proxy
#if __GLASGOW_HASKELL__ < 804
import Data.Semigroup
#endif
import Foreign.Ptr (castPtr)
import Foreign.Storable
import GHC.TypeLits
import GHC.Types (Type)
newtype Identity a
= Identity { getIdentity :: a }
deriving ( Functor
, Foldable
, Traversable
, Storable
, Eq
, Ord
)
data Thunk a
= Thunk { getThunk :: a }
deriving ( Functor
, Foldable
, Traversable
)
newtype Lift (op :: l -> l' -> *) (f :: k -> l) (g :: k -> l') (x :: k)
= Lift { getLift :: op (f x) (g x) }
newtype Compose (f :: l -> *) (g :: k -> l) (x :: k)
= Compose { getCompose :: f (g x) }
deriving (Storable)
type f :. g = Compose f g
infixr 9 :.
newtype Const (a :: *) (b :: k)
= Const { getConst :: a }
deriving ( Functor
, Foldable
, Traversable
, Storable
)
data ElField (field :: (Symbol, Type)) where
Field :: KnownSymbol s => !t -> ElField '(s,t)
deriving instance Eq t => Eq (ElField '(s,t))
deriving instance Ord t => Ord (ElField '(s,t))
instance (Num t, KnownSymbol s) => Num (ElField '(s,t)) where
Field x + Field y = Field (x+y)
Field x * Field y = Field (x*y)
abs (Field x) = Field (abs x)
signum (Field x) = Field (signum x)
fromInteger = Field . fromInteger
negate (Field x) = Field (negate x)
instance Semigroup t => Semigroup (ElField '(s,t)) where
Field x <> Field y = Field (x <> y)
instance (KnownSymbol s, Monoid t) => Monoid (ElField '(s,t)) where
mempty = Field mempty
mappend (Field x) (Field y) = Field (mappend x y)
instance (Real t, KnownSymbol s) => Real (ElField '(s,t)) where
toRational (Field x) = toRational x
instance (Fractional t, KnownSymbol s) => Fractional (ElField '(s,t)) where
fromRational = Field . fromRational
Field x / Field y = Field (x / y)
instance (Floating t, KnownSymbol s) => Floating (ElField '(s,t)) where
pi = Field pi
exp (Field x) = Field (exp x)
log (Field x) = Field (log x)
sin (Field x) = Field (sin x)
cos (Field x) = Field (cos x)
asin (Field x) = Field (asin x)
acos (Field x) = Field (acos x)
atan (Field x) = Field (atan x)
sinh (Field x) = Field (sinh x)
cosh (Field x) = Field (cosh x)
asinh (Field x) = Field (asinh x)
acosh (Field x) = Field (acosh x)
atanh (Field x) = Field (atanh x)
instance (RealFrac t, KnownSymbol s) => RealFrac (ElField '(s,t)) where
properFraction (Field x) = fmap Field (properFraction x)
instance (Show t, KnownSymbol s) => Show (ElField '(s,t)) where
show (Field x) = symbolVal (Proxy::Proxy s) ++" :-> "++show x
instance forall s t. (KnownSymbol s, Storable t)
=> Storable (ElField '(s,t)) where
sizeOf _ = sizeOf (undefined::t)
alignment _ = alignment (undefined::t)
peek ptr = Field `fmap` peek (castPtr ptr)
poke ptr (Field x) = poke (castPtr ptr) x
instance Show a => Show (Const a b) where
show (Const x) = "(Const "++show x ++")"
instance Eq a => Eq (Const a b) where
Const x == Const y = x == y
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
instance (Foldable f, Foldable g) => Foldable (Compose f g) where
foldMap f (Compose t) = foldMap (foldMap f) t
instance (Traversable f, Traversable g) => Traversable (Compose f g) where
traverse f (Compose t) = Compose <$> traverse (traverse f) t
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
instance Show (f (g a)) => Show (Compose f g a) where
show (Compose x) = show x
instance Applicative Identity where
pure = Identity
Identity f <*> Identity x = Identity (f x)
instance Monad Identity where
return = Identity
Identity x >>= f = f x
instance Show a => Show (Identity a) where
show (Identity x) = show x
instance Applicative Thunk where
pure = Thunk
(Thunk f) <*> (Thunk x) = Thunk (f x)
instance Monad Thunk where
return = Thunk
(Thunk x) >>= f = f x
instance Show a => Show (Thunk a) where
show (Thunk x) = show x
instance (Functor f, Functor g) => Functor (Lift (,) f g) where
fmap f (Lift (x, y)) = Lift (fmap f x, fmap f y)
instance (Functor f, Functor g) => Functor (Lift Either f g) where
fmap f (Lift (Left x)) = Lift . Left . fmap f $ x
fmap f (Lift (Right x)) = Lift . Right . fmap f $ x
instance (Applicative f, Applicative g) => Applicative (Lift (,) f g) where
pure x = Lift (pure x, pure x)
Lift (f, g) <*> Lift (x, y) = Lift (f <*> x, g <*> y)