{-# 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 :: forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp _ x :: f a ix
x s :: String
s = (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> f a ix -> String
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IShow f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> f a ix -> String
ishow forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp f a ix
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s
    ishow :: SingI ix => (forall ix. SingI ix => Int -> a ix -> ShowS) -> f a ix -> String
    ishow sp :: forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp x :: f a ix
x = (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> f a ix -> ShowS
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IShow f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> f a ix -> ShowS
ishowsPrec forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp 0 f a ix
x ""
    {-# MINIMAL ishowsPrec | ishow #-}

class IShow2 a where
    ishowsPrec2 :: SingI ix => Int -> a ix -> ShowS
    ishowsPrec2 _ x :: a ix
x s :: String
s = a ix -> String
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
a ix -> String
ishow2 a ix
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s
    ishow2 :: SingI ix => a ix -> String
    ishow2 x :: a ix
x = Int -> a ix -> ShowS
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
Int -> a ix -> ShowS
ishowsPrec2 0 a ix
x ""
    {-# MINIMAL ishowsPrec2 | ishow2 #-}

ishowsPrec1 :: (IShow f, IShow2 a, SingI ix) => Int -> f a ix -> ShowS
ishowsPrec1 :: Int -> f a ix -> ShowS
ishowsPrec1 = (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> f a ix -> ShowS
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IShow f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> f a ix -> ShowS
ishowsPrec forall (ix :: k). SingI ix => Int -> a ix -> ShowS
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
Int -> a ix -> ShowS
ishowsPrec2

ishow1 :: (IShow f, IShow2 a, SingI ix) => f a ix -> String
ishow1 :: f a ix -> String
ishow1 = (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> f a ix -> String
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IShow f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> f a ix -> String
ishow forall (ix :: k). SingI ix => Int -> a ix -> ShowS
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
Int -> a ix -> ShowS
ishowsPrec2

class IRead f where
    ireadPrec :: SingI ix => (forall ix. SingI ix => ReadPrec (a ix)) -> ReadPrec (f a ix)
    ireadPrec rp :: forall (ix :: k). SingI ix => ReadPrec (a ix)
rp = (Int -> ReadS (f a ix)) -> ReadPrec (f a ix)
forall a. (Int -> ReadS a) -> ReadPrec a
readS_to_Prec ((Int -> ReadS (f a ix)) -> ReadPrec (f a ix))
-> (Int -> ReadS (f a ix)) -> ReadPrec (f a ix)
forall a b. (a -> b) -> a -> b
$ (forall (ix :: k). SingI ix => Int -> ReadS (a ix))
-> Int -> ReadS (f a ix)
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IRead f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> ReadS (a ix))
-> Int -> ReadS (f a ix)
ireadsPrec (ReadPrec (a ix) -> Int -> ReadS (a ix)
forall a. ReadPrec a -> Int -> ReadS a
readPrec_to_S ReadPrec (a ix)
forall (ix :: k). SingI ix => ReadPrec (a ix)
rp)
    ireadsPrec :: SingI ix => (forall ix. SingI ix => Int -> ReadS (a ix)) -> Int -> ReadS (f a ix)
    ireadsPrec rp :: forall (ix :: k). SingI ix => Int -> ReadS (a ix)
rp = ReadPrec (f a ix) -> Int -> ReadS (f a ix)
forall a. ReadPrec a -> Int -> ReadS a
readPrec_to_S (ReadPrec (f a ix) -> Int -> ReadS (f a ix))
-> ReadPrec (f a ix) -> Int -> ReadS (f a ix)
forall a b. (a -> b) -> a -> b
$ (forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (f a ix)
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IRead f, SingI ix) =>
(forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (f a ix)
ireadPrec ((Int -> ReadS (a ix)) -> ReadPrec (a ix)
forall a. (Int -> ReadS a) -> ReadPrec a
readS_to_Prec Int -> ReadS (a ix)
forall (ix :: k). SingI ix => Int -> ReadS (a ix)
rp)
    {-# MINIMAL ireadPrec | ireadsPrec #-}

class IRead2 a where
    ireadPrec2 :: SingI ix => ReadPrec (a ix)
    ireadPrec2 = (Int -> ReadS (a ix)) -> ReadPrec (a ix)
forall a. (Int -> ReadS a) -> ReadPrec a
readS_to_Prec ((Int -> ReadS (a ix)) -> ReadPrec (a ix))
-> (Int -> ReadS (a ix)) -> ReadPrec (a ix)
forall a b. (a -> b) -> a -> b
$ Int -> ReadS (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
Int -> ReadS (a ix)
ireadsPrec2
    ireadsPrec2 :: SingI ix => Int -> ReadS (a ix)
    ireadsPrec2 = ReadPrec (a ix) -> Int -> ReadS (a ix)
forall a. ReadPrec a -> Int -> ReadS a
readPrec_to_S (ReadPrec (a ix) -> Int -> ReadS (a ix))
-> ReadPrec (a ix) -> Int -> ReadS (a ix)
forall a b. (a -> b) -> a -> b
$ ReadPrec (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
ReadPrec (a ix)
ireadPrec2
    {-# MINIMAL ireadPrec2 | ireadsPrec2 #-}

ireadPrec1 :: (IRead f, IRead2 a, SingI ix) => ReadPrec (f a ix)
ireadPrec1 :: ReadPrec (f a ix)
ireadPrec1 = (forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (f a ix)
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IRead f, SingI ix) =>
(forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (f a ix)
ireadPrec forall (ix :: k). SingI ix => ReadPrec (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
ReadPrec (a ix)
ireadPrec2

ireadsPrec1 :: (IRead f, IRead2 a, SingI ix) => Int -> ReadS (f a ix)
ireadsPrec1 :: Int -> ReadS (f a ix)
ireadsPrec1 = (forall (ix :: k). SingI ix => Int -> ReadS (a ix))
-> Int -> ReadS (f a ix)
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IRead f, SingI ix) =>
(forall (ix :: k). SingI ix => Int -> ReadS (a ix))
-> Int -> ReadS (f a ix)
ireadsPrec forall (ix :: k). SingI ix => Int -> ReadS (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
Int -> ReadS (a ix)
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 :: f a ix -> f a ix -> Bool
ieq1 = (forall (ix :: k). SingI ix => a ix -> a ix -> Bool)
-> f a ix -> f a ix -> Bool
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IEq f, SingI ix) =>
(forall (ix :: k). SingI ix => a ix -> a ix -> Bool)
-> f a ix -> f a ix -> Bool
ieq forall (ix :: k). SingI ix => a ix -> a ix -> Bool
forall k (a :: k -> *) (ix :: k).
(IEq2 a, SingI ix) =>
a ix -> a ix -> Bool
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 :: f a ix -> f a ix -> Ordering
icompare1 = (forall (ix :: k). SingI ix => a ix -> a ix -> Ordering)
-> f a ix -> f a ix -> Ordering
forall k k (f :: (k -> *) -> k -> *) (ix :: k) (a :: k -> *).
(IOrd f, SingI ix) =>
(forall (ix :: k). SingI ix => a ix -> a ix -> Ordering)
-> f a ix -> f a ix -> Ordering
icompare forall (ix :: k). SingI ix => a ix -> a ix -> Ordering
forall k (a :: k -> *) (ix :: k).
(IOrd2 a, SingI ix) =>
a ix -> a ix -> Ordering
icompare2

-- * base instances

-- Sum
instance IShow2 a => IShow (Sum a) where
    ishowsPrec :: (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> Sum a a ix -> ShowS
ishowsPrec _ p :: Int
p (InL x :: a ix
x) = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString "InL " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a ix -> ShowS
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
Int -> a ix -> ShowS
ishowsPrec2 11 a ix
x
    ishowsPrec sp :: forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp p :: Int
p (InR x :: a ix
x) = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString "InR " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a ix -> ShowS
forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp 11 a ix
x

instance IRead2 a => IRead (Sum a) where
    ireadPrec :: (forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (Sum a a ix)
ireadPrec rp :: forall (ix :: k). SingI ix => ReadPrec (a ix)
rp = ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix))
-> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a b. (a -> b) -> a -> b
$
        (Int -> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a. Int -> ReadPrec a -> ReadPrec a
prec 10 (ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix))
-> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a b. (a -> b) -> a -> b
$ do
            Ident "InL" <- ReadPrec Lexeme
lexP
            a ix
x <- ReadPrec (a ix) -> ReadPrec (a ix)
forall a. ReadPrec a -> ReadPrec a
step ReadPrec (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
ReadPrec (a ix)
ireadPrec2
            Sum a a ix -> ReadPrec (Sum a a ix)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Sum a a ix -> ReadPrec (Sum a a ix))
-> Sum a a ix -> ReadPrec (Sum a a ix)
forall a b. (a -> b) -> a -> b
$ a ix -> Sum a a ix
forall k (f :: k -> *) (g :: k -> *) (a :: k). f a -> Sum f g a
InL a ix
x
        )
        ReadPrec (Sum a a ix)
-> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a. ReadPrec a -> ReadPrec a -> ReadPrec a
+++
        (Int -> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a. Int -> ReadPrec a -> ReadPrec a
prec 10 (ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix))
-> ReadPrec (Sum a a ix) -> ReadPrec (Sum a a ix)
forall a b. (a -> b) -> a -> b
$ do
            Ident "InR" <- ReadPrec Lexeme
lexP
            a ix
x <- ReadPrec (a ix) -> ReadPrec (a ix)
forall a. ReadPrec a -> ReadPrec a
step ReadPrec (a ix)
forall (ix :: k). SingI ix => ReadPrec (a ix)
rp
            Sum a a ix -> ReadPrec (Sum a a ix)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Sum a a ix -> ReadPrec (Sum a a ix))
-> Sum a a ix -> ReadPrec (Sum a a ix)
forall a b. (a -> b) -> a -> b
$ a ix -> Sum a a ix
forall k (f :: k -> *) (g :: k -> *) (a :: k). g a -> Sum f g a
InR a ix
x
        )

instance IEq2 a => IEq (Sum a) where
    ieq :: (forall (ix :: k). SingI ix => a ix -> a ix -> Bool)
-> Sum a a ix -> Sum a a ix -> Bool
ieq _  (InL x :: a ix
x) (InL y :: a ix
y) = a ix -> a ix -> Bool
forall k (a :: k -> *) (ix :: k).
(IEq2 a, SingI ix) =>
a ix -> a ix -> Bool
ieq2 a ix
x a ix
y
    ieq eq :: forall (ix :: k). SingI ix => a ix -> a ix -> Bool
eq (InR x :: a ix
x) (InR y :: a ix
y) = a ix -> a ix -> Bool
forall (ix :: k). SingI ix => a ix -> a ix -> Bool
eq a ix
x a ix
y
    ieq _ _ _              = Bool
False

instance IOrd2 a => IOrd (Sum a) where
    icompare :: (forall (ix :: k). SingI ix => a ix -> a ix -> Ordering)
-> Sum a a ix -> Sum a a ix -> Ordering
icompare _ (InL x :: a ix
x) (InL y :: a ix
y)    = a ix -> a ix -> Ordering
forall k (a :: k -> *) (ix :: k).
(IOrd2 a, SingI ix) =>
a ix -> a ix -> Ordering
icompare2 a ix
x a ix
y
    icompare comp :: forall (ix :: k). SingI ix => a ix -> a ix -> Ordering
comp (InR x :: a ix
x) (InR y :: a ix
y) = a ix -> a ix -> Ordering
forall (ix :: k). SingI ix => a ix -> a ix -> Ordering
comp a ix
x a ix
y
    icompare _ (InL _) (InR _)    = Ordering
LT
    icompare _ (InR _) (InL _)    = Ordering
GT

-- Product
instance IShow2 a => IShow (Product a) where
    ishowsPrec :: (forall (ix :: k). SingI ix => Int -> a ix -> ShowS)
-> Int -> Product a a ix -> ShowS
ishowsPrec sp :: forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp p :: Int
p (Pair a :: a ix
a b :: a ix
b) = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString "Pair " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a ix -> ShowS
forall k (a :: k -> *) (ix :: k).
(IShow2 a, SingI ix) =>
Int -> a ix -> ShowS
ishowsPrec2 11 a ix
a ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString " " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a ix -> ShowS
forall (ix :: k). SingI ix => Int -> a ix -> ShowS
sp 11 a ix
b

instance IRead2 a => IRead (Product a) where
    ireadPrec :: (forall (ix :: k). SingI ix => ReadPrec (a ix))
-> ReadPrec (Product a a ix)
ireadPrec rp :: forall (ix :: k). SingI ix => ReadPrec (a ix)
rp = ReadPrec (Product a a ix) -> ReadPrec (Product a a ix)
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec (Product a a ix) -> ReadPrec (Product a a ix))
-> ReadPrec (Product a a ix) -> ReadPrec (Product a a ix)
forall a b. (a -> b) -> a -> b
$ Int -> ReadPrec (Product a a ix) -> ReadPrec (Product a a ix)
forall a. Int -> ReadPrec a -> ReadPrec a
prec 10 (ReadPrec (Product a a ix) -> ReadPrec (Product a a ix))
-> ReadPrec (Product a a ix) -> ReadPrec (Product a a ix)
forall a b. (a -> b) -> a -> b
$ do
        Ident "Pair" <- ReadPrec Lexeme
lexP
        a ix
x <- ReadPrec (a ix) -> ReadPrec (a ix)
forall a. ReadPrec a -> ReadPrec a
step ReadPrec (a ix)
forall k (a :: k -> *) (ix :: k).
(IRead2 a, SingI ix) =>
ReadPrec (a ix)
ireadPrec2
        a ix
y <- ReadPrec (a ix) -> ReadPrec (a ix)
forall a. ReadPrec a -> ReadPrec a
step ReadPrec (a ix)
forall (ix :: k). SingI ix => ReadPrec (a ix)
rp
        Product a a ix -> ReadPrec (Product a a ix)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Product a a ix -> ReadPrec (Product a a ix))
-> Product a a ix -> ReadPrec (Product a a ix)
forall a b. (a -> b) -> a -> b
$ a ix -> a ix -> Product a a ix
forall k (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair a ix
x a ix
y

instance IEq2 a => IEq (Product a) where
    ieq :: (forall (ix :: k). SingI ix => a ix -> a ix -> Bool)
-> Product a a ix -> Product a a ix -> Bool
ieq eq :: forall (ix :: k). SingI ix => a ix -> a ix -> Bool
eq (Pair a :: a ix
a b :: a ix
b) (Pair a' :: a ix
a' b' :: a ix
b') = a ix -> a ix -> Bool
forall k (a :: k -> *) (ix :: k).
(IEq2 a, SingI ix) =>
a ix -> a ix -> Bool
ieq2 a ix
a a ix
a' Bool -> Bool -> Bool
&& a ix -> a ix -> Bool
forall (ix :: k). SingI ix => a ix -> a ix -> Bool
eq a ix
b a ix
b'

instance IOrd2 a => IOrd (Product a) where
    icompare :: (forall (ix :: k). SingI ix => a ix -> a ix -> Ordering)
-> Product a a ix -> Product a a ix -> Ordering
icompare comp :: forall (ix :: k). SingI ix => a ix -> a ix -> Ordering
comp (Pair a :: a ix
a b :: a ix
b) (Pair a' :: a ix
a' b' :: a ix
b') = a ix -> a ix -> Ordering
forall k (a :: k -> *) (ix :: k).
(IOrd2 a, SingI ix) =>
a ix -> a ix -> Ordering
icompare2 a ix
a a ix
a' Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> a ix -> a ix -> Ordering
forall (ix :: k). SingI ix => a ix -> a ix -> Ordering
comp a ix
b a ix
b'