{-# language CPP #-}
{-# language DataKinds #-}
{-# language DefaultSignatures #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language GADTs #-}
{-# language PolyKinds #-}
{-# language ScopedTypeVariables #-}
{-# language TypeInType #-}
{-# language TypeOperators #-}
{-# language UndecidableInstances #-}
{-# OPTIONS_HADDOCK not-home #-}
module Data.Lazify.Internal (
Lazifiable (..)
, GLazifiable (..)
, GIsNewtype (..)
, genericLazify
, ($~)
) where
import GHC.Generics
import Data.Functor.Product
import Data.Proxy
import Data.Functor.Identity (Identity)
import Data.Functor.Compose (Compose)
import Data.Coerce (Coercible)
import Data.Type.Coercion (Coercion(..))
import Control.Applicative (Const)
import GHC.Exts (TYPE)
import Data.Type.Equality ((:~:)(..))
import qualified Data.Monoid as M
import qualified Data.Semigroup as S
#if MIN_VERSION_base(4,10,0)
import Data.Type.Equality ((:~~:)(..), type (~~))
import Type.Reflection (Typeable, TypeRep, typeRep)
#endif
class Lazifiable a where
lazify :: a -> a
default lazify :: (Generic a, GLazifiable (Rep a)) => a -> a
lazify x = genericLazify x
class GLazifiable f where
glazify :: f a -> f a
genericLazify :: (Generic a, GLazifiable (Rep a)) => a -> a
genericLazify = to . glazify . from
($~) :: forall rep a (b :: TYPE rep). Lazifiable a => (a -> b) -> a -> b
f $~ a = f (lazify a)
instance GLazifiable f => GLazifiable (D1 ('MetaData x y z 'False) f) where
glazify (M1 x) = M1 (glazify x)
instance GLazifiable f => GLazifiable (C1 c f) where
glazify (M1 x) = M1 (glazify x)
instance GLazifiable f => GLazifiable (S1 c f) where
glazify (M1 x) = M1 (glazify x)
instance GIsNewtype f => GLazifiable (D1 ('MetaData x y z 'True) f) where
glazify (M1 x) = M1 (glazifyNewtype x)
instance GLazifiable (K1 i c) where
glazify x = x
instance GLazifiable U1 where
glazify _ = U1
instance (GLazifiable f, GLazifiable g) => GLazifiable (f :*: g) where
glazify ~(x :*: y) = glazify x :*: glazify y
class GIsNewtype f where
glazifyNewtype :: f a -> f a
instance GIsNewtype f => GIsNewtype (M1 i c f) where
glazifyNewtype (M1 x) = M1 (glazifyNewtype x)
instance Lazifiable a => GIsNewtype (K1 i a) where
glazifyNewtype (K1 a) = K1 (lazify a)
instance Lazifiable (Proxy a)
instance Lazifiable (Product f g a)
instance Lazifiable a => Lazifiable (Identity a)
instance Lazifiable a => Lazifiable (Const a b)
instance Lazifiable (f (g a)) => Lazifiable (Compose f g a)
instance Lazifiable a => Lazifiable (S.First a)
instance Lazifiable a => Lazifiable (S.Last a)
instance Lazifiable a => Lazifiable (S.Min a)
instance Lazifiable a => Lazifiable (S.Max a)
instance Lazifiable (S.Arg a b)
instance Lazifiable a => Lazifiable (M.Sum a)
instance Lazifiable a => Lazifiable (M.Product a)
instance Lazifiable (f a) => Lazifiable (M.Alt f a)
#if MIN_VERSION_base(4,12,0)
instance Lazifiable (f a) => Lazifiable (M.Ap f a)
#endif
instance a ~ b => Lazifiable (a :~: b) where
lazify _ = Refl
instance Coercible a b => Lazifiable (Coercion a b) where
lazify _ = Coercion
#if MIN_VERSION_base(4,10,0)
instance a ~~ b => Lazifiable (a :~~: b) where
lazify _ = HRefl
instance Typeable a => Lazifiable (TypeRep a) where
lazify _ = typeRep
#endif
instance Lazifiable ()
instance Lazifiable (a,b)
instance Lazifiable (a,b,c)
instance Lazifiable (a,b,c,d)
instance Lazifiable (a,b,c,d,e)
instance Lazifiable (a,b,c,d,e,f)
instance Lazifiable (a,b,c,d,e,f,g)
instance Lazifiable (a,b,c,d,e,f,g,h) where
lazify ~(a,b,c,d,e,f,g,h) = (a,b,c,d,e,f,g,h)
instance Lazifiable (a,b,c,d,e,f,g,h,i) where
lazify ~(a,b,c,d,e,f,g,h,i) = (a,b,c,d,e,f,g,h,i)
instance Lazifiable (a,b,c,d,e,f,g,h,i,j) where
lazify ~(a,b,c,d,e,f,g,h,i,j) = (a,b,c,d,e,f,g,h,i,j)