{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Data.Singletons.Prelude.Semigroup (
PSemigroup(..), SSemigroup(..),
Sing(SMin, sGetMin, SMax, sGetMax,
SFirst, sGetFirst, SLast, sGetLast,
SWrapMonoid, sUnwrapMonoid, SDual, sGetDual,
SAll, sGetAll, SAny, sGetAny,
SSum, sGetSum, SProduct, sGetProduct,
SOption, sGetOption, SArg),
GetMin, GetMax, GetFirst, GetLast, GetDual,
GetAll, GetAny, GetSum, GetProduct, GetOption,
SMin, SMax, SFirst, SLast, SWrappedMonoid, SDual,
SAll, SAny, SSum, SProduct, SOption, SArg,
option_, sOption_, Option_,
type (<>@#@$), type (<>@#@$$), type (<>@#@$$$),
SconcatSym0, SconcatSym1,
MinSym0, MinSym1, GetMinSym0, GetMinSym1,
MaxSym0, MaxSym1, GetMaxSym0, GetMaxSym1,
FirstSym0, FirstSym1, GetFirstSym0, GetFirstSym1,
LastSym0, LastSym1, GetLastSym0, GetLastSym1,
WrapMonoidSym0, WrapMonoidSym1, UnwrapMonoidSym0, UnwrapMonoidSym1,
DualSym0, DualSym1, GetDualSym0, GetDualSym1,
AllSym0, AllSym1, GetAllSym0, GetAllSym1,
AnySym0, AnySym1, GetAnySym0, GetAnySym1,
SumSym0, SumSym1, GetSumSym0, GetSumSym1,
ProductSym0, ProductSym1, GetProductSym0, GetProductSym1,
OptionSym0, OptionSym1, GetOptionSym0, GetOptionSym1,
ArgSym0, ArgSym1, ArgSym2
) where
import Control.Applicative
import Control.Monad
import qualified Data.Semigroup as Semi (Min(..), Max(..))
import Data.Semigroup (First(..), Last(..), WrappedMonoid(..), Option(..), Arg(..))
import Data.Singletons.Prelude.Base hiding
(Foldr, FoldrSym0, FoldrSym1, FoldrSym2, FoldrSym3, sFoldr)
import Data.Singletons.Prelude.Enum
import Data.Singletons.Prelude.Eq
import Data.Singletons.Prelude.Foldable hiding
( All, AllSym0, AllSym1
, Any, AnySym0, AnySym1
, Product, ProductSym0, ProductSym1
, Sum, SumSym0, SumSym1 )
import Data.Singletons.Prelude.Functor
import Data.Singletons.Prelude.Instances
import Data.Singletons.Prelude.Maybe
import Data.Singletons.Prelude.Monad.Internal
import Data.Singletons.Prelude.Monoid hiding
(Sing(SFirst, SLast), SFirst, sGetFirst, SLast, sGetLast,
FirstSym0, FirstSym1, LastSym0, LastSym1,
GetFirst, GetFirstSym0, GetFirstSym1,
GetLast, GetLastSym0, GetLastSym1)
import Data.Singletons.Prelude.Num
import Data.Singletons.Prelude.Ord hiding
(MinSym0, MinSym1, MaxSym0, MaxSym1)
import Data.Singletons.Prelude.Semigroup.Internal
import Data.Singletons.Prelude.Show
import Data.Singletons.Prelude.Traversable
import Data.Singletons.Single
import Data.Singletons.Util
$(genSingletons [''Arg])
$(showSingInstances $ ''Option : semigroupBasicTypes)
$(singShowInstances $ ''Option : semigroupBasicTypes)
$(singletonsOnly [d|
instance Applicative Semi.Min where
pure = Semi.Min
a <* _ = a
_ *> a = a
Semi.Min f <*> Semi.Min x = Semi.Min (f x)
liftA2 f (Semi.Min a) (Semi.Min b) = Semi.Min (f a b)
instance Enum a => Enum (Semi.Min a) where
succ (Semi.Min a) = Semi.Min (succ a)
pred (Semi.Min a) = Semi.Min (pred a)
toEnum = Semi.Min . toEnum
fromEnum (Semi.Min a) = fromEnum a
enumFromTo (Semi.Min a) (Semi.Min b) = Semi.Min `map` enumFromTo a b
enumFromThenTo (Semi.Min a) (Semi.Min b) (Semi.Min c) = Semi.Min `map` enumFromThenTo a b c
deriving instance Functor Semi.Min
instance Monad Semi.Min where
(>>) = (*>)
Semi.Min a >>= f = f a
instance Ord a => Semigroup (Semi.Min a) where
Semi.Min a <> Semi.Min b = Semi.Min (a `min_` b)
instance (Ord a, Bounded a) => Monoid (Semi.Min a) where
mempty = maxBound
instance Num a => Num (Semi.Min a) where
(Semi.Min a) + (Semi.Min b) = Semi.Min (a + b)
(Semi.Min a) * (Semi.Min b) = Semi.Min (a * b)
(Semi.Min a) - (Semi.Min b) = Semi.Min (a - b)
negate (Semi.Min a) = Semi.Min (negate a)
abs (Semi.Min a) = Semi.Min (abs a)
signum (Semi.Min a) = Semi.Min (signum a)
fromInteger = Semi.Min . fromInteger
deriving instance Foldable Semi.Min
deriving instance Traversable Semi.Min
instance Applicative Semi.Max where
pure = Semi.Max
a <* _ = a
_ *> a = a
Semi.Max f <*> Semi.Max x = Semi.Max (f x)
liftA2 f (Semi.Max a) (Semi.Max b) = Semi.Max (f a b)
instance Enum a => Enum (Semi.Max a) where
succ (Semi.Max a) = Semi.Max (succ a)
pred (Semi.Max a) = Semi.Max (pred a)
toEnum = Semi.Max . toEnum
fromEnum (Semi.Max a) = fromEnum a
enumFromTo (Semi.Max a) (Semi.Max b) = Semi.Max `map` enumFromTo a b
enumFromThenTo (Semi.Max a) (Semi.Max b) (Semi.Max c) = Semi.Max `map` enumFromThenTo a b c
deriving instance Functor Semi.Max
instance Monad Semi.Max where
(>>) = (*>)
Semi.Max a >>= f = f a
instance Ord a => Semigroup (Semi.Max a) where
Semi.Max a <> Semi.Max b = Semi.Max (a `max_` b)
instance (Ord a, Bounded a) => Monoid (Semi.Max a) where
mempty = minBound
instance Num a => Num (Semi.Max a) where
(Semi.Max a) + (Semi.Max b) = Semi.Max (a + b)
(Semi.Max a) * (Semi.Max b) = Semi.Max (a * b)
(Semi.Max a) - (Semi.Max b) = Semi.Max (a - b)
negate (Semi.Max a) = Semi.Max (negate a)
abs (Semi.Max a) = Semi.Max (abs a)
signum (Semi.Max a) = Semi.Max (signum a)
fromInteger = Semi.Max . fromInteger
deriving instance Foldable Semi.Max
deriving instance Traversable Semi.Max
instance Eq a => Eq (Arg a b) where
Arg a _ == Arg b _ = a == b
deriving instance Functor (Arg a)
instance Ord a => Ord (Arg a b) where
Arg a _ `compare` Arg b _ = compare a b
min x@(Arg a _) y@(Arg b _)
| a <= b = x
| otherwise = y
max x@(Arg a _) y@(Arg b _)
| a >= b = x
| otherwise = y
deriving instance (Show a, Show b) => Show (Arg a b)
deriving instance Foldable (Arg a)
deriving instance Traversable (Arg a)
instance Applicative First where
pure x = First x
a <* _ = a
_ *> a = a
First f <*> First x = First (f x)
liftA2 f (First a) (First b) = First (f a b)
instance Enum a => Enum (First a) where
succ (First a) = First (succ a)
pred (First a) = First (pred a)
toEnum = First . toEnum
fromEnum (First a) = fromEnum a
enumFromTo (First a) (First b) = First `map` enumFromTo a b
enumFromThenTo (First a) (First b) (First c) = First `map` enumFromThenTo a b c
deriving instance Functor First
instance Monad First where
(>>) = (*>)
First a >>= f = f a
instance Semigroup (First a) where
a <> _ = a
deriving instance Foldable First
deriving instance Traversable First
instance Applicative Last where
pure x = Last x
a <* _ = a
_ *> a = a
Last f <*> Last x = Last (f x)
liftA2 f (Last a) (Last b) = Last (f a b)
instance Enum a => Enum (Last a) where
succ (Last a) = Last (succ a)
pred (Last a) = Last (pred a)
toEnum = Last . toEnum
fromEnum (Last a) = fromEnum a
enumFromTo (Last a) (Last b) = Last `map` enumFromTo a b
enumFromThenTo (Last a) (Last b) (Last c) = Last `map` enumFromThenTo a b c
deriving instance Functor Last
instance Monad Last where
(>>) = (*>)
Last a >>= f = f a
instance Semigroup (Last a) where
_ <> b = b
deriving instance Foldable Last
deriving instance Traversable Last
instance Monoid m => Semigroup (WrappedMonoid m) where
WrapMonoid a <> WrapMonoid b = WrapMonoid (a `mappend` b)
instance Monoid m => Monoid (WrappedMonoid m) where
mempty = WrapMonoid mempty
instance Enum a => Enum (WrappedMonoid a) where
succ (WrapMonoid a) = WrapMonoid (succ a)
pred (WrapMonoid a) = WrapMonoid (pred a)
toEnum = WrapMonoid . toEnum
fromEnum (WrapMonoid a) = fromEnum a
enumFromTo (WrapMonoid a) (WrapMonoid b) = WrapMonoid `map` enumFromTo a b
enumFromThenTo (WrapMonoid a) (WrapMonoid b) (WrapMonoid c) =
WrapMonoid `map` enumFromThenTo a b c
instance Alternative Option where
empty = Option Nothing
Option Nothing <|> b = b
a@(Option Just{}) <|> _ = a
instance Applicative Option where
pure a = Option (Just a)
Option a <*> Option b = Option (a <*> b)
liftA2 f (Option x) (Option y) = Option (liftA2 f x y)
Option Nothing *> _ = Option Nothing
Option Just{} *> b = b
deriving instance Functor Option
instance Monad Option where
Option (Just a) >>= k = k a
Option Nothing >>= _ = Option Nothing
(>>) = (*>)
instance MonadPlus Option
instance Semigroup a => Semigroup (Option a) where
Option a <> Option b = Option (a <> b)
instance Semigroup a => Monoid (Option a) where
mempty = Option Nothing
instance Foldable Option where
foldMap f (Option (Just m)) = f m
foldMap _ (Option Nothing) = mempty
instance Traversable Option where
traverse f (Option (Just a)) = Option . Just <$> f a
traverse _ (Option Nothing) = pure (Option Nothing)
|])
$(singletons [d|
option_ :: b -> (a -> b) -> Option a -> b
option_ n j (Option m) = maybe_ n j m
|])