{-# 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 -- Copyright : (C) 2018 Ryan Scott -- License : BSD-style (see LICENSE) -- Maintainer : Ryan Scott -- Stability : experimental -- Portability : non-portable -- -- Defines the promoted version of 'Semigroup', 'PSemigroup', and the -- singleton version, 'SSemigroup'. -- ---------------------------------------------------------------------------- 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_, -- ** Defunctionalization symbols 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 -- deriving newtype instance Semigroup a => Semigroup (Option a) 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| -- Renamed to avoid name clash -- -| Fold an 'Option' case-wise, just like 'maybe'. option_ :: b -> (a -> b) -> Option a -> b option_ n j (Option m) = maybe_ n j m |])