ten-0.1.0.0: src/Data/Ten/Functor.hs
-- Copyright 2018-2021 Google LLC
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- | Provides an analog of 'Functor' over arity-1 type constructors.
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Ten.Functor
( Functor10(..), (<$!), (<$>!), void10
) where
import Data.Kind (Type)
import Data.Proxy (Proxy(..))
import GHC.Generics
( Generic1(..)
, (:.:)(..), (:*:)(..), (:+:)(..)
, M1(..), Rec1(..), U1(..), V1, K1(..)
)
import Data.Wrapped (Wrapped1(..))
import Data.Ten.Ap (Ap10(..))
-- | 'Functor' over arity-1 type constructors.
--
-- Whereas 'Functor' maps @a :: Type@ values to @b :: Type@ values, 'Functor10'
-- maps @(m :: k -> Type) a@ values to @m b@ values, parametrically in @a@.
-- That is, the type parameter of 'Functor' has arity 0, and the type
-- parameter of 'Functor10' has arity 1.
class Functor10 (f :: (k -> Type) -> Type) where
-- | Map each @m a@ value in @f m@ parametrically to @n a@ to get @f m@.
fmap10 :: (forall a. m a -> n a) -> f m -> f n
instance (Generic1 f, Functor10 (Rep1 f))
=> Functor10 (Wrapped1 Generic1 f) where
fmap10 f = Wrapped1 . to1 . fmap10 f . from1 . unWrapped1
instance Functor10 (Ap10 a) where
fmap10 f (Ap10 x) = Ap10 (f x)
instance Functor10 (K1 i a) where
fmap10 _ (K1 x) = K1 x
instance Functor10 V1 where
fmap10 _ x = case x of {}
instance Functor10 U1 where
fmap10 _ U1 = U1
deriving instance Functor10 f => Functor10 (Rec1 f)
deriving instance Functor10 f => Functor10 (M1 i c f)
instance (Functor10 f, Functor10 g) => Functor10 (f :+: g) where
fmap10 f (L1 x) = L1 (fmap10 f x)
fmap10 f (R1 x) = R1 (fmap10 f x)
instance (Functor10 f, Functor10 g) => Functor10 (f :*: g) where
fmap10 f (l :*: r) = fmap10 f l :*: fmap10 f r
instance (Functor f, Functor10 g) => Functor10 (f :.: g) where
fmap10 f (Comp1 x) = Comp1 $ fmap (fmap10 f) x
infixl 4 <$!
-- | ('<$') for 'Functor10'.
(<$!) :: Functor10 f => (forall a. n a) -> f m -> f n
x <$! f = fmap10 (const x) f
infixl 4 <$>!
-- | ('<$>') for 'Functor10'.
(<$>!) :: Functor10 f => (forall a. m a -> n a) -> f m -> f n
(<$>!) = fmap10
-- | 'Data.Functor.void' for 'Functor10'.
--
-- This returns @f 'Proxy'@ because @Proxy :: k -> Type@ has the right kind and
-- carries no runtime information. It's isomorphic to @Const ()@ but easier to
-- spell.
void10 :: Functor10 f => f m -> f Proxy
void10 = fmap10 (const Proxy)