{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# OPTIONS_GHC -Wall -Wno-name-shadowing #-}
module Data.IFunctor.Classes
(
-- * Indexed Show
IShow (..)
, IShow2 (..)
, ishowsPrec1
, ishow1
-- * Indexed Read
, IRead (..)
, IRead2 (..)
, ireadPrec1
, ireadsPrec1
-- * Indexed Eq
, IEq (..)
, IEq2 (..)
, ieq1
-- * Indexed Ord
, IOrd (..)
, IOrd2 (..)
, icompare1
) where
import Data.Functor.Product (Product (..))
import Data.Functor.Sum (Sum (..))
import Singlethongs (SingI)
import Text.Read
class IShow f where
ishowsPrec :: SingI ix => (forall ix. SingI ix => Int -> a ix -> ShowS) -> Int -> f a ix -> ShowS
ishowsPrec sp _ x s = ishow sp x ++ s
ishow :: SingI ix => (forall ix. SingI ix => Int -> a ix -> ShowS) -> f a ix -> String
ishow sp x = ishowsPrec sp 0 x ""
{-# MINIMAL ishowsPrec | ishow #-}
class IShow2 a where
ishowsPrec2 :: SingI ix => Int -> a ix -> ShowS
ishowsPrec2 _ x s = ishow2 x ++ s
ishow2 :: SingI ix => a ix -> String
ishow2 x = ishowsPrec2 0 x ""
{-# MINIMAL ishowsPrec2 | ishow2 #-}
ishowsPrec1 :: (IShow f, IShow2 a, SingI ix) => Int -> f a ix -> ShowS
ishowsPrec1 = ishowsPrec ishowsPrec2
ishow1 :: (IShow f, IShow2 a, SingI ix) => f a ix -> String
ishow1 = ishow ishowsPrec2
class IRead f where
ireadPrec :: SingI ix => (forall ix. SingI ix => ReadPrec (a ix)) -> ReadPrec (f a ix)
ireadPrec rp = readS_to_Prec $ ireadsPrec (readPrec_to_S rp)
ireadsPrec :: SingI ix => (forall ix. SingI ix => Int -> ReadS (a ix)) -> Int -> ReadS (f a ix)
ireadsPrec rp = readPrec_to_S $ ireadPrec (readS_to_Prec rp)
{-# MINIMAL ireadPrec | ireadsPrec #-}
class IRead2 a where
ireadPrec2 :: SingI ix => ReadPrec (a ix)
ireadPrec2 = readS_to_Prec $ ireadsPrec2
ireadsPrec2 :: SingI ix => Int -> ReadS (a ix)
ireadsPrec2 = readPrec_to_S $ ireadPrec2
{-# MINIMAL ireadPrec2 | ireadsPrec2 #-}
ireadPrec1 :: (IRead f, IRead2 a, SingI ix) => ReadPrec (f a ix)
ireadPrec1 = ireadPrec ireadPrec2
ireadsPrec1 :: (IRead f, IRead2 a, SingI ix) => Int -> ReadS (f a ix)
ireadsPrec1 = ireadsPrec ireadsPrec2
class IEq f where
ieq :: SingI ix => (forall ix. SingI ix => a ix -> a ix -> Bool) -> f a ix -> f a ix -> Bool
class IEq2 a where
ieq2 :: SingI ix => a ix -> a ix -> Bool
ieq1 :: (IEq f, IEq2 a, SingI ix) => f a ix -> f a ix -> Bool
ieq1 = ieq ieq2
class IEq f => IOrd f where
icompare :: SingI ix => (forall ix. SingI ix => a ix -> a ix -> Ordering) -> f a ix -> f a ix -> Ordering
class IEq2 a => IOrd2 a where
icompare2 :: SingI ix => a ix -> a ix -> Ordering
icompare1 :: (IOrd f, IOrd2 a, SingI ix) => f a ix -> f a ix -> Ordering
icompare1 = icompare icompare2
-- * base instances
-- Sum
instance IShow2 a => IShow (Sum a) where
ishowsPrec _ p (InL x) = showParen (p > 10) $
showString "InL " . ishowsPrec2 11 x
ishowsPrec sp p (InR x) = showParen (p > 10) $
showString "InR " . sp 11 x
instance IRead2 a => IRead (Sum a) where
ireadPrec rp = parens $
(prec 10 $ do
Ident "InL" <- lexP
x <- step ireadPrec2
pure $ InL x
)
+++
(prec 10 $ do
Ident "InR" <- lexP
x <- step rp
pure $ InR x
)
instance IEq2 a => IEq (Sum a) where
ieq _ (InL x) (InL y) = ieq2 x y
ieq eq (InR x) (InR y) = eq x y
ieq _ _ _ = False
instance IOrd2 a => IOrd (Sum a) where
icompare _ (InL x) (InL y) = icompare2 x y
icompare comp (InR x) (InR y) = comp x y
icompare _ (InL _) (InR _) = LT
icompare _ (InR _) (InL _) = GT
-- Product
instance IShow2 a => IShow (Product a) where
ishowsPrec sp p (Pair a b) = showParen (p > 10) $
showString "Pair " . ishowsPrec2 11 a . showString " " . sp 11 b
instance IRead2 a => IRead (Product a) where
ireadPrec rp = parens $ prec 10 $ do
Ident "Pair" <- lexP
x <- step ireadPrec2
y <- step rp
pure $ Pair x y
instance IEq2 a => IEq (Product a) where
ieq eq (Pair a b) (Pair a' b') = ieq2 a a' && eq b b'
instance IOrd2 a => IOrd (Product a) where
icompare comp (Pair a b) (Pair a' b') = icompare2 a a' <> comp b b'