{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
module Test where
import Data.DeriveLiftedInstances
import Data.Functor.Identity
class Test a where
op0 :: a
op1 :: Int -> [a] -> a
op2 :: [[a]] -> a
instance Test Int where
op0 = 1
op1 i is = i + sum is
op2 = sum . fmap sum
newtype X = X { unX :: Int } deriving Show
mkX :: Int -> X
mkX = X . (`mod` 10)
deriveInstance (isoDeriv [| mkX |] [| unX |] idDeriv) [t| Num X |]
deriveInstance (isoDeriv [| mkX |] [| unX |] idDeriv) [t| Test X |]
deriveInstance (isoDeriv [| mkX |] [| unX |] idDeriv) [t| Eq X |]
deriveInstance (isoDeriv [| mkX |] [| unX |] idDeriv) [t| Ord X |]
data Rec f = Rec { getUnit :: f (), getInt :: f Int, getX :: f X }
deriving instance (Show (f ()), Show (f Int), Show (f X)) => Show (Rec f)
deriving instance (Eq (f ()), Eq (f Int), Eq (f X)) => Eq (Rec f)
-- deriveInstance (recordDeriv [| Rec |]
-- [ ([| getUnit |], apDeriv monoidDeriv)
-- , ([| getInt |], apDeriv idDeriv)
-- , ([| getX |], apDeriv (isoDeriv [| mkX |] [| unX |] idDeriv))
-- ]) [t| forall f. (Applicative f, Foldable f, Ord (f ()), Ord (f Int), Ord (f X)) => Ord (Rec f) |]
deriveInstance showDeriv [t| Test ShowsPrec |]
deriveInstance monoidDeriv [t| Test () |]
deriveInstance (apDeriv idDeriv) [t| forall a. Test a => Test [a] |]
-- deriveInstance (biapDeriv idDeriv idDeriv) [t| forall a b. (Test a, Test b) => Test (a, b) |]
-- deriveInstance (newtypeDeriv 'Identity 'runIdentity idDeriv) [t| forall a. Test a => Test (Identity a) |]
deriveInstance (apDeriv monoidDeriv) [t| forall a. Monoid a => Test (IO a) |]
newtype Ap f a = Ap { getAp :: f a } deriving Show
deriveInstance (newtypeDeriv 'Ap 'getAp (apDeriv idDeriv)) [t| forall f a. (Applicative f, Test a) => Test (Ap f a) |]
deriveInstance (newtypeDeriv 'Identity 'runIdentity (newtypeDeriv 'Ap 'getAp (apDeriv idDeriv))) [t| forall f a. (Applicative f, Test a) => Test (Identity (Ap f a)) |]
newtype Id a = Id { runId :: a }
deriveInstance (apDeriv (apDeriv (newtypeDeriv 'Id 'runId idDeriv))) [t| forall a. Test a => Test (() -> Identity (Id a)) |]
deriveInstance (apDeriv (biapDeriv idDeriv idDeriv)) [t| forall a b. (Test a, Test b) => Test (() -> (a, b)) |]
deriveInstance (biapDeriv (apDeriv idDeriv) (newtypeDeriv 'Id 'runId idDeriv)) [t| forall a b. (Test a, Test b) => Test (() -> a, Id b) |]
deriveInstance (biapDeriv (monoidDerivBy [| (+) |] [| 0 |]) (monoidDerivBy [| (*) |] [| 1 |])) [t| Test (Int, Int) |]
class Test1 f where
hop0 :: f a
hop0' :: f Int
hop1 :: Int -> f Int -> f Int
instance Test1 [] where
hop0 = []
hop0' = [1]
hop1 i = map (+ i)
deriveInstance (newtypeDeriv 'Ap 'getAp idDeriv) [t| forall f. Test1 f => Test1 (Ap f) |]
deriveInstance (newtypeDeriv 'Ap 'getAp idDeriv) [t| forall f. Functor f => Functor (Ap f) |]
deriveInstance (newtypeDeriv 'Ap 'getAp idDeriv) [t| forall f. Applicative f => Applicative (Ap f) |]
deriveInstance (newtypeDeriv 'Ap 'getAp idDeriv) [t| forall f. Monad f => Monad (Ap f) |]
class Cotest a where
co0 :: a -> Int
co1 :: Int -> a -> a
co2 :: a -> [[a]]
instance (Cotest a, Cotest b) => Cotest (Either a b) where
co0 a = either co0 co0 a
co1 i a = either (Left . co1 i) (Right . co1 i) a
co2 a = either (fmap (fmap Left) . co2) (fmap (fmap Right) . co2) a
data Cofree c b where
Cofree :: c a => (a -> b) -> a -> Cofree c b
instance Cotest (Cofree Cotest a) where
co0 (Cofree _ a) = co0 a
co1 i (Cofree k a) = Cofree k (co1 i a)
co2 (Cofree k a) = fmap (fmap (Cofree k)) (co2 a)