{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Data.Singletons.Prelude.Semigroup.Internal where
import Data.List.NonEmpty (NonEmpty(..))
import Data.Ord (Down(..))
import Data.Proxy
import Data.Semigroup (Dual(..), All(..), Any(..), Sum(..), Product(..), Option(..))
import Data.Singletons.Internal
import Data.Singletons.Prelude.Base
import Data.Singletons.Prelude.Bool
import Data.Singletons.Prelude.Enum
import Data.Singletons.Prelude.Eq
import Data.Singletons.Prelude.Instances
import Data.Singletons.Prelude.Monad.Internal
import Data.Singletons.Prelude.Num
import Data.Singletons.Prelude.Ord hiding (MinSym0, MinSym1, MaxSym0, MaxSym1)
import Data.Singletons.Promote
import Data.Singletons.Single
import Data.Singletons.TypeLits.Internal
import Data.Singletons.Util
import qualified Data.Text as T
import Data.Void (Void)
import GHC.TypeLits (AppendSymbol, SomeSymbol(..), someSymbolVal, Symbol)
import Unsafe.Coerce
$(singletonsOnly [d|
class Semigroup a where
(<>) :: a -> a -> a
infixr 6 <>
sconcat :: NonEmpty a -> a
sconcat (a :| as) = go a as where
go b (c:cs) = b <> go c cs
go b [] = b
instance Semigroup [a] where
(<>) = (++)
instance Semigroup (NonEmpty a) where
(a :| as) <> (b :| bs) = a :| (as ++ b : bs)
instance Semigroup b => Semigroup (a -> b) where
f <> g = \x -> f x <> g x
instance Semigroup () where
_ <> _ = ()
sconcat _ = ()
instance (Semigroup a, Semigroup b) => Semigroup (a, b) where
(a,b) <> (a',b') = (a<>a',b<>b')
instance (Semigroup a, Semigroup b, Semigroup c) => Semigroup (a, b, c) where
(a,b,c) <> (a',b',c') = (a<>a',b<>b',c<>c')
instance (Semigroup a, Semigroup b, Semigroup c, Semigroup d)
=> Semigroup (a, b, c, d) where
(a,b,c,d) <> (a',b',c',d') = (a<>a',b<>b',c<>c',d<>d')
instance (Semigroup a, Semigroup b, Semigroup c, Semigroup d, Semigroup e)
=> Semigroup (a, b, c, d, e) where
(a,b,c,d,e) <> (a',b',c',d',e') = (a<>a',b<>b',c<>c',d<>d',e<>e')
instance Semigroup Ordering where
LT <> _ = LT
EQ <> y = y
GT <> _ = GT
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> b = b
a <> Nothing = a
Just a <> Just b = Just (a <> b)
instance Semigroup (Either a b) where
Left _ <> b = b
a@Right{} <> _ = a
instance Semigroup Void where
a <> _ = a
instance Semigroup a => Semigroup (Down a) where
Down a <> Down b = Down (a <> b)
|])
infixr 6 <>
$(genSingletons $ ''Option : semigroupBasicTypes)
$(singBoundedInstances semigroupBasicTypes)
$(singEqInstances $ ''Option : semigroupBasicTypes)
$(singDecideInstances $ ''Option : semigroupBasicTypes)
$(singOrdInstances $ ''Option : semigroupBasicTypes)
$(singletonsOnly [d|
instance Applicative Dual where
pure = Dual
Dual f <*> Dual x = Dual (f x)
deriving instance Functor Dual
instance Monad Dual where
Dual a >>= k = k a
instance Semigroup a => Semigroup (Dual a) where
Dual a <> Dual b = Dual (b <> a)
instance Semigroup All where
All a <> All b = All (a && b)
instance Semigroup Any where
Any a <> Any b = Any (a || b)
instance Applicative Sum where
pure = Sum
Sum f <*> Sum x = Sum (f x)
deriving instance Functor Sum
instance Monad Sum where
Sum a >>= k = k a
instance Num a => Semigroup (Sum a) where
Sum a <> Sum b = Sum (a + b)
instance Num a => Num (Sum a) where
Sum a + Sum b = Sum (a + b)
Sum a - Sum b = Sum (a - b)
Sum a * Sum b = Sum (a * b)
negate (Sum a) = Sum (negate a)
abs (Sum a) = Sum (abs a)
signum (Sum a) = Sum (signum a)
fromInteger n = Sum (fromInteger n)
instance Applicative Product where
pure = Product
Product f <*> Product x = Product (f x)
deriving instance Functor Product
instance Monad Product where
Product a >>= k = k a
instance Num a => Semigroup (Product a) where
Product a <> Product b = Product (a * b)
instance Num a => Num (Product a) where
Product a + Product b = Product (a + b)
Product a - Product b = Product (a - b)
Product a * Product b = Product (a * b)
negate (Product a) = Product (negate a)
abs (Product a) = Product (abs a)
signum (Product a) = Product (signum a)
fromInteger n = Product (fromInteger n)
|])
instance PSemigroup Symbol where
type a <> b = AppendSymbol a b
instance SSemigroup Symbol where
sa %<> sb =
let a = fromSing sa
b = fromSing sb
ex = someSymbolVal $ T.unpack $ a <> b
in case ex of
SomeSymbol (_ :: Proxy ab) -> unsafeCoerce (SSym :: Sing ab)
min_, max_ :: Ord a => a -> a -> a
min_ = min
max_ = max
type Min_ x y = Min x y
type Max_ x y = Max x y
$(genDefunSymbols [''Min_, ''Max_])
sMin_ :: forall a (x :: a) (y :: a). SOrd a => Sing x -> Sing y -> Sing (x `Min_` y)
sMin_ = sMin
sMax_ :: forall a (x :: a) (y :: a). SOrd a => Sing x -> Sing y -> Sing (x `Max_` y)
sMax_ = sMax
all_ :: Bool -> All
all_ = All
any_ :: Bool -> Any
any_ = Any
sum_ :: a -> Sum a
sum_ = Sum
product_ :: a -> Product a
product_ = Product
type All_ a = 'All a
type Any_ a = 'Any a
type Sum_ a = 'Sum a
type Product_ a = 'Product a
$(genDefunSymbols [''All_, ''Any_, ''Sum_, ''Product_])
sAll_ :: forall (x :: Bool). Sing x -> Sing (All_ x)
sAll_ = SAll
sAny_ :: forall (x :: Bool). Sing x -> Sing (Any_ x)
sAny_ = SAny
sSum_ :: forall a (x :: a). Sing x -> Sing (Sum_ x)
sSum_ = SSum
sProduct_ :: forall a (x :: a). Sing x -> Sing (Product_ x)
sProduct_ = SProduct