{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE CPP #-}
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
------------------------------------------------------------------------------- |-- Module : Data.Profunctor.Rep-- Copyright : (C) 2011-2012 Edward Kmett,-- License : BSD-style (see the file LICENSE)---- Maintainer : Edward Kmett <ekmett@gmail.com>-- Stability : provisional-- Portability : Type-Families------------------------------------------------------------------------------
module Data.Profunctor.Rep
(
-- * Representable Profunctors
Representable(..), tabulated
-- * Corepresentable Profunctors
, Corepresentable(..), cotabulated
) where
import Control.Arrow
import Control.Comonad
import Data.Functor.Identity
import Data.Profunctor
import Data.Proxy
import Data.Tagged
-- * Representable Profunctors-- | A 'Profunctor' @p@ is 'Representable' if there exists a 'Functor' @f@ such that-- @p d c@ is isomorphic to @d -> f c@.
class (Functor (Rep p), Profunctor p) =>Representablep where
type Rep p :: * -> *tabulate :: (d -> Reppc) -> pdcrep :: pdc -> d -> Reppc
instance Representable(->) where
type Rep (->) = Identitytabulatef = runIdentity.f{-# INLINE tabulate #-}repf = Identity.f{-# INLINE rep #-}
instance (Monad m, Functor m) =>Representable (Kleislim) where
type Rep (Kleisli m) = mtabulate = Kleisli{-# INLINE tabulate #-}rep = runKleisli{-# INLINE rep #-}
instance Functor f =>Representable (UpStarf) where
type Rep (UpStar f) = ftabulate = UpStar{-# INLINE tabulate #-}rep = runUpStar{-# INLINE rep #-}type Iso s t a b = forall p f. (Profunctor p, Functor f) => p a (f b) -> p s (f t)-- | 'tabulate' and 'rep' form two halves of an isomorphism.---- This can be used with the combinators from the @lens@ package.---- @'tabulated' :: 'Representable' p => 'Iso'' (d -> 'Rep' p c) (p d c)@tabulated :: (Representable p, Representable q) =>Iso (d -> Reppc) (d' -> Repqc') (pdc) (qd'c')
tabulated = dimaptabulate (fmaprep)
{-# INLINE tabulated #-}-- * Corepresentable Profunctors-- | A 'Profunctor' @p@ is 'Corepresentable' if there exists a 'Functor' @f@ such that-- @p d c@ is isomorphic to @f d -> c@.
class (Functor (Corep p), Profunctor p) =>Corepresentablep where
type Corep p :: * -> *cotabulate :: (Coreppd -> c) -> pdccorep :: pdc -> Coreppd -> c
instance Corepresentable(->) where
type Corep (->) = Identitycotabulatef = f.Identity{-# INLINE cotabulate #-}corepf (Identityd) = fd{-# INLINE corep #-}
instance Functor w =>Corepresentable (Cokleisliw) where
type Corep (Cokleisli w) = wcotabulate = Cokleisli{-# INLINE cotabulate #-}corep = runCokleisli{-# INLINE corep #-}
instance CorepresentableTagged where
type Corep Tagged = Proxycotabulatef = Tagged (fProxy)
{-# INLINE cotabulate #-}corep (Taggeda) _ = a{-# INLINE corep #-}
instance Functor f =>Corepresentable (DownStarf) where
type Corep (DownStar f) = fcotabulate = DownStar{-# INLINE cotabulate #-}corep = runDownStar{-# INLINE corep #-}-- | 'cotabulate' and 'corep' form two halves of an isomorphism.---- This can be used with the combinators from the @lens@ package.---- @'tabulated' :: 'Corep' f p => 'Iso'' (f d -> c) (p d c)@cotabulated :: (Corepresentable p, Corepresentable q) =>Iso (Coreppd -> c) (Corepqd' -> c') (pdc) (qd'c')
cotabulated = dimapcotabulate (fmapcorep)
{-# INLINE cotabulated #-}