one-liner-instances 0.1.0.0 → 0.1.1.0
raw patch · 8 files changed
+471/−48 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.Monoid.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints (Data.Monoid.OneLiner.GMonoid a) Data.Semigroup.Semigroup) => Data.Semigroup.Semigroup (Data.Monoid.OneLiner.GMonoid a)
- Data.Monoid.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints (Data.Monoid.OneLiner.GMonoid a) GHC.Base.Monoid) => GHC.Base.Monoid (Data.Monoid.OneLiner.GMonoid a)
- Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints (Numeric.OneLiner.GNum a) GHC.Float.Floating) => GHC.Float.Floating (Numeric.OneLiner.GNum a)
- Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints (Numeric.OneLiner.GNum a) GHC.Num.Num) => GHC.Num.Num (Numeric.OneLiner.GNum a)
- Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints (Numeric.OneLiner.GNum a) GHC.Real.Fractional) => GHC.Real.Fractional (Numeric.OneLiner.GNum a)
+ Data.Bounded.OneLiner: GBounded :: a -> GBounded a
+ Data.Bounded.OneLiner: [getGBounded] :: GBounded a -> a
+ Data.Bounded.OneLiner: gMaxBound :: forall a. (ADT a, Constraints a Bounded) => a
+ Data.Bounded.OneLiner: gMinBound :: forall a. (ADT a, Constraints a Bounded) => a
+ Data.Bounded.OneLiner: instance (Generics.OneLiner.Internal.ADT a, Generics.OneLiner.Internal.Constraints a GHC.Enum.Bounded) => GHC.Enum.Bounded (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance Data.Data.Data a => Data.Data.Data (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance Data.Foldable.Foldable Data.Bounded.OneLiner.GBounded
+ Data.Bounded.OneLiner: instance Data.Traversable.Traversable Data.Bounded.OneLiner.GBounded
+ Data.Bounded.OneLiner: instance GHC.Base.Functor Data.Bounded.OneLiner.GBounded
+ Data.Bounded.OneLiner: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance GHC.Generics.Generic (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance GHC.Read.Read a => GHC.Read.Read (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: instance GHC.Show.Show a => GHC.Show.Show (Data.Bounded.OneLiner.GBounded a)
+ Data.Bounded.OneLiner: newtype GBounded a
+ Data.Monoid.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints a Data.Semigroup.Semigroup) => Data.Semigroup.Semigroup (Data.Monoid.OneLiner.GMonoid a)
+ Data.Monoid.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints a Data.Semigroup.Semigroup, Generics.OneLiner.Internal.Constraints a GHC.Base.Monoid) => GHC.Base.Monoid (Data.Monoid.OneLiner.GMonoid a)
+ Data.Ord.OneLiner: GOrd :: a -> GOrd a
+ Data.Ord.OneLiner: [getGOrd] :: GOrd a -> a
+ Data.Ord.OneLiner: gCompare :: forall a. (ADT a, Constraints a Ord) => a -> a -> Ordering
+ Data.Ord.OneLiner: gEquals :: forall a. (ADT a, Constraints a Eq) => a -> a -> Bool
+ Data.Ord.OneLiner: gGT :: forall a. (ADT a, Constraints a Ord) => a -> a -> Bool
+ Data.Ord.OneLiner: gGTE :: forall a. (ADT a, Constraints a Ord) => a -> a -> Bool
+ Data.Ord.OneLiner: gLT :: forall a. (ADT a, Constraints a Ord) => a -> a -> Bool
+ Data.Ord.OneLiner: gLTE :: forall a. (ADT a, Constraints a Ord) => a -> a -> Bool
+ Data.Ord.OneLiner: gMax :: forall a. (ADT a, Constraints a Ord) => a -> a -> a
+ Data.Ord.OneLiner: gMin :: forall a. (ADT a, Constraints a Ord) => a -> a -> a
+ Data.Ord.OneLiner: gNotEquals :: forall a. (ADT a, Constraints a Eq) => a -> a -> Bool
+ Data.Ord.OneLiner: instance (Generics.OneLiner.Internal.ADT a, Generics.OneLiner.Internal.Constraints a GHC.Classes.Eq) => GHC.Classes.Eq (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: instance (Generics.OneLiner.Internal.ADT a, Generics.OneLiner.Internal.Constraints a GHC.Classes.Eq, Generics.OneLiner.Internal.Constraints a GHC.Classes.Ord) => GHC.Classes.Ord (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: instance Data.Data.Data a => Data.Data.Data (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: instance Data.Foldable.Foldable Data.Ord.OneLiner.GOrd
+ Data.Ord.OneLiner: instance Data.Traversable.Traversable Data.Ord.OneLiner.GOrd
+ Data.Ord.OneLiner: instance GHC.Base.Functor Data.Ord.OneLiner.GOrd
+ Data.Ord.OneLiner: instance GHC.Generics.Generic (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: instance GHC.Read.Read a => GHC.Read.Read (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: instance GHC.Show.Show a => GHC.Show.Show (Data.Ord.OneLiner.GOrd a)
+ Data.Ord.OneLiner: newtype GOrd a
+ Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints a GHC.Num.Num) => GHC.Num.Num (Numeric.OneLiner.GNum a)
+ Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints a GHC.Num.Num, Generics.OneLiner.Internal.Constraints a GHC.Real.Fractional) => GHC.Real.Fractional (Numeric.OneLiner.GNum a)
+ Numeric.OneLiner: instance (Generics.OneLiner.Internal.ADTRecord a, Generics.OneLiner.Internal.Constraints a GHC.Num.Num, Generics.OneLiner.Internal.Constraints a GHC.Real.Fractional, Generics.OneLiner.Internal.Constraints a GHC.Float.Floating) => GHC.Float.Floating (Numeric.OneLiner.GNum a)
Files
- CHANGELOG.md +14/−0
- README.md +54/−2
- one-liner-instances.cabal +6/−3
- src/Data/Bounded/OneLiner.hs +80/−0
- src/Data/Monoid/OneLiner.hs +24/−8
- src/Data/Ord/OneLiner.hs +171/−0
- src/Generics/OneLiner/Instances/Internal.hs +22/−0
- src/Numeric/OneLiner.hs +100/−35
CHANGELOG.md view
@@ -1,10 +1,24 @@ Changelog ========= +Version 0.1.1.0+---------------++*Feb 5, 2018*++<https://github.com/mstksg/one-liner-instances/releases/tag/v0.1.1.0>++* Newtype instances actually didn't work before! They do now :)+* Added generic implementations and newtypes for `Bounded`, `Ord`, and `Eq`.+* Some aggressive inlining in all modules.+* Added clarification and comparisons to other libraries to README+ Version 0.1.0.0 --------------- *Feb 3, 2018*++**Deprecated** <https://github.com/mstksg/one-liner-instances/releases/tag/v0.1.0.0>
README.md view
@@ -3,9 +3,12 @@ This package uses machinery from *[one-liner][]* in order to provide default implementations for methods from `Num`, `Fractional`, `Floating`, `Semigroup`,-and `Monoid`. These will work for any types (deriving `Generic`) that are-made with one constructor, whose fields are all instances of that typeclass.+`Monoid`, `Bounded`, `Eq`, and `Ord`. These will work for any types (deriving+`Generic`) whose fields are all instances of that typeclass. +For `Num`, `Fractional`, `Floating`, `Semigroup`, and `Monoid`, the types also+must have only a single constructor.+ [one-liner]: https://hackage.haskell.org/package/one-liner So, `gPlus` (generic addition) will work for:@@ -39,3 +42,52 @@ If `a` is a data type (deriving `Generic`) with a single constructor whose fields all have instances of `Semigroup`, then `GMonoid a` has a `Semigroup` instance (and same for `Monoid`).++If `a` is a data type (deriving `Generic`) whose fields all have instances of+`Bounded`, then `GBounded a` has a `Bounded` instance.++If `a` is a data type (deriving `Generic`) whose fields all have instances of+`Eq`, then `GOrd a` has a `Eq` instance (and same for+`Ord`).++Comparisons+-----------++This package provides very similar functionality to *[generic-deriving][]*.++[generic-deriving]: http://hackage.haskell.org/package/generic-deriving++There are a few major design differences between *generic-deriving* and+*one-liner*, the package that this one is built on.++*generic-deriving* creates a *separate* "deriving" typeclass for every+typeclass one wants to generalize. So, there is a separate `GMonoid`+typeclass, a separate `GEnum` typeclass, etc.++*one-liner* instead creates a single typeclass (`ADTRecord` and `Constraints`)+to unify all generalizable typeclasses. Both the generic `Monoid` and generic+`Num` instances are built upon the same `Constraints` typeclass. From a+usability standpoint, *one-liner* allows one to easily create generic versions+of their own, custom typeclasses -- something that *generic-deriving* does not+help with.++*one-liner-instances*, however, is simply a package using the *one-liner*+engine to provide generic instances for common classes where it is possible.++The main difference in practical usability between *one-liner-instances* and+*generic-deriving* themselves are few, but are mainly:++* *one-liner-instances* has generic implementations for+ `Num`/`Fractional`/`Floating`, and *generic-deriving* doesn't. This is a+ superficial difference, however, since nothing fundamental is preventing+ *generic-deriving* from adding them in the future.+* *one-liner-instances* provides newtype wrappers that can automatically+ imbue appropriate types with instances, which can be used with the upcoming+ [DerivingVia][] syntax to automatically derive instances, or just used on+ their own for convenience purposes.++ *generic-deriving* does not aim to do this at this moment.+* Integrates with the rest of the *one-liner* ecosystem, if one is already+ using it to provide constraints for custom typeclasses.++[DerivingVia]: https://twitter.com/Iceland_jack/status/959923603096719360
one-liner-instances.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 74fd58c6e43032c81d9051e316cb272e628fed2738e586fca65ac7e4c62fc0c1+-- hash: 95c2f55c56790e15fd9320018faf309e137158787294ce8fa8024dde4348a9fa name: one-liner-instances-version: 0.1.0.0+version: 0.1.1.0 synopsis: Generics-based implementations for common typeclasses description: Provides generics-based implementations for common typeclasses using Generics. For now, has implementations for Numeric typeclasses (Num,@@ -39,8 +39,11 @@ base >=4.7 && <5 , one-liner >=0.9 exposed-modules:- Numeric.OneLiner+ Data.Bounded.OneLiner Data.Monoid.OneLiner+ Data.Ord.OneLiner+ Numeric.OneLiner other-modules:+ Generics.OneLiner.Instances.Internal Paths_one_liner_instances default-language: Haskell2010
+ src/Data/Bounded/OneLiner.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UndecidableInstances #-}++-- |+-- Module : Data.Bounded.OneLiner+-- Description : Derived methods for Semigroup.+-- Copyright : (c) Justin Le 2018+-- License : BSD-3+-- Maintainer : justin@jle.im+-- Stability : unstable+-- Portability : portable+--+-- Derived methods for 'Bounded', using "Generics.OneLiner" and+-- "GHC.Generics".+--+-- Can be used for any types (deriving 'Generic') where every field is an+-- instance of 'Bounded'.+--+-- Also includes a newtype wrapper that imbues any such data type with an+-- instant 'Bounded' instance, which can one day be used with /DerivingVia/+-- syntax to derive instances automatically.+--++module Data.Bounded.OneLiner (+ -- * Newtype wrapper+ GBounded(..)+ -- * Generics-derived methods+ , gMinBound+ , gMaxBound+ ) where++import Data.Data+import GHC.Generics+import Generics.OneLiner+import Generics.OneLiner.Instances.Internal++-- | If @a@ is a data type whose fields are all instances of 'Bounded',+-- then @'GBounded' a@ has a 'Bounded' instance.+--+-- Will one day be able to be used with /DerivingVia/ syntax, to derive+-- instances automatically.+--+newtype GBounded a = GBounded { getGBounded :: a }+ deriving (Eq, Ord, Show, Read, Data, Generic, Functor, Foldable, Traversable)++instance ( ADT a+ , Constraints a Bounded+ )+ => Bounded (GBounded a) where+ minBound = c0 (gMinBound @a)+ {-# INLINE minBound #-}+ maxBound = c0 (gMaxBound @a)+ {-# INLINE maxBound #-}++-- | 'minBound' implemented by using 'minBound' for all of the components+-- for the first constructor+gMinBound+ :: forall a. (ADT a, Constraints a Bounded)+ => a+gMinBound = case create @Bounded [minBound] of+ [] -> error "minBound: uninhabited"+ x:_ -> x+{-# INLINE gMinBound #-}++-- | 'maxBound' implemented by using 'maxBound' for all of the components+-- for the last constructor+gMaxBound+ :: forall a. (ADT a, Constraints a Bounded)+ => a+gMaxBound = case reverse (create @Bounded [maxBound]) of+ [] -> error "maxBound: uninhabited"+ x:_ -> x+{-# INLINE gMaxBound #-}
src/Data/Monoid/OneLiner.hs view
@@ -17,15 +17,16 @@ -- Stability : unstable -- Portability : portable ----- Derived methods for Semigroup and Monoid, using "Generics.OneLiner" and--- "GHC.Generics".+-- Derived methods for 'Semigroup' and 'Monoid', using "Generics.OneLiner"+-- and "GHC.Generics". -- -- Can be used for any types (deriving 'Generic') made with a single -- constructor, where every field is an instance of 'Semigroup' (or -- 'Monoid', depending on the function). -- -- Also includes a newtype wrapper that imbues any such data type with--- instant 'Semigroup' and 'Monoid' instances.+-- instant 'Semigroup' and 'Monoid' instances, which can one day be used+-- with /DerivingVia/ syntax to derive instances automatically. -- module Data.Monoid.OneLiner (@@ -43,6 +44,7 @@ import Data.Semigroup import GHC.Generics import Generics.OneLiner+import Generics.OneLiner.Instances.Internal -- | If @a@ is a data type with a single constructor whose fields are all -- instances of 'Semigroup', then @'GMonoid' a@ has a 'Semigroup' instance.@@ -50,17 +52,28 @@ -- If @a@ is a data type with a single constructor whose fields are all -- instances of 'Monoid', then @'GMonoid' a@ has a 'Monoid' instance. --+-- Will one day be able to be used with /DerivingVia/ syntax, to derive+-- instances automatically.+-- newtype GMonoid a = GMonoid { getGMonoid :: a } deriving (Eq, Ord, Show, Read, Data, Generic, Functor, Foldable, Traversable) -instance (ADTRecord a, Constraints (GMonoid a) Semigroup)+instance ( ADTRecord a+ , Constraints a Semigroup+ ) => Semigroup (GMonoid a) where- (<>) = gSemigroup @(GMonoid a)+ (<>) = c2 (gSemigroup @a)+ {-# INLINE (<>) #-} -instance (ADTRecord a, Constraints (GMonoid a) Monoid)+instance ( ADTRecord a+ , Constraints a Semigroup+ , Constraints a Monoid+ ) => Monoid (GMonoid a) where- mappend = gMappend- mempty = gMempty+ mappend = c2 (gMappend @a)+ {-# INLINE mappend #-}+ mempty = c0 (gMempty @a)+ {-# INLINE mempty #-} -- | Semigroup append ('<>') implemented by calling '<>' on the components.@@ -68,6 +81,7 @@ :: forall a. (ADTRecord a, Constraints a Semigroup) => a -> a -> a gSemigroup = binaryOp @Semigroup (<>)+{-# INLINE gSemigroup #-} -- | Monoid append ('mappend') implemented by calling '<>' on the -- components.@@ -75,6 +89,7 @@ :: forall a. (ADTRecord a, Constraints a Monoid) => a -> a -> a gMappend = binaryOp @Monoid mappend+{-# INLINE gMappend #-} -- | Monoid identity ('mempty') implemented by using 'mempty' for all of -- the components.@@ -82,4 +97,5 @@ :: forall a. (ADTRecord a, Constraints a Monoid) => a gMempty = nullaryOp @Monoid mempty+{-# INLINE gMempty #-}
+ src/Data/Ord/OneLiner.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UndecidableInstances #-}++-- |+-- Module : Data.Ord.OneLiner+-- Description : Derived methods for Semigroup.+-- Copyright : (c) Justin Le 2018+-- License : BSD-3+-- Maintainer : justin@jle.im+-- Stability : unstable+-- Portability : portable+--+-- Derived methods for 'Eq' and 'Ord', using "Generics.OneLiner" and+-- "GHC.Generics".+--+-- Can be used for any types (deriving 'Generic') where every field is an+-- instance of 'Eq' (or 'Ord').+--+-- Also includes a newtype wrapper that imbues any such data type with+-- instant 'Eq' and 'Ord' instances, which can one day be used with+-- /DerivingVia/ syntax to derive instances automatically.+--++module Data.Ord.OneLiner (+ -- * Newtype wrapper+ GOrd(..)+ -- * Generics-derived methods+ -- ** Eq+ , gEquals+ , gNotEquals+ -- ** Ord+ , gCompare+ , gLTE+ , gLT+ , gGTE+ , gGT+ , gMax+ , gMin+ ) where++import Data.Data+import Data.Monoid+import GHC.Generics+import Generics.OneLiner+import Generics.OneLiner.Instances.Internal++-- | If @a@ is a data type whose fields are all instances of 'Eq', then+-- @'GOrd' a@ has a 'Eq' instance.+--+-- If @a@ is a data type whose fields are all instances of 'Ord', then+-- @'GOrd' a@ has a 'Ord' instance.+--+-- Will one day be able to be used with /DerivingVia/ syntax, to derive+-- instances automatically.+--+newtype GOrd a = GOrd { getGOrd :: a }+ deriving (Show, Read, Data, Generic, Functor, Foldable, Traversable)++instance ( ADT a+ , Constraints a Eq+ )+ => Eq (GOrd a) where+ (==) = c2' (gEquals @a)+ {-# INLINE (==) #-}+ (/=) = c2' (gNotEquals @a)+ {-# INLINE (/=) #-}++instance ( ADT a+ , Constraints a Eq+ , Constraints a Ord+ )+ => Ord (GOrd a) where+ compare = c2' (gCompare @a)+ {-# INLINE compare #-}+ (<=) = c2' (gLTE @a)+ {-# INLINE (<=) #-}+ (<) = c2' (gLT @a)+ {-# INLINE (<) #-}+ (>=) = c2' (gGTE @a)+ {-# INLINE (>=) #-}+ (>) = c2' (gGT @a)+ {-# INLINE (>) #-}+ max = c2 (gMax @a)+ {-# INLINE max #-}+ min = c2 (gMin @a)+ {-# INLINE min #-}++-- | '==' implemented by using '==' between all of the+-- components, lexicographically. First compares constructors.+gEquals+ :: forall a. (ADT a, Constraints a Eq)+ => a -> a -> Bool+gEquals x y = ctorIndex x == ctorIndex y+ && getAll (mzipWith @Eq (\x' -> All . (== x')) x y)+{-# INLINE gEquals #-}++-- | '/=' implemented by using '/=' between all of the+-- components, lexicographically. First compares constructors.+gNotEquals+ :: forall a. (ADT a, Constraints a Eq)+ => a -> a -> Bool+gNotEquals x y = ctorIndex x /= ctorIndex y+ || getAny (mzipWith @Eq (\x' -> Any . (/= x')) x y)+{-# INLINE gNotEquals #-}++-- | 'compare' implemented by using 'compare' between all of the+-- components, lexicographically. First compares constructors.+gCompare+ :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> Ordering+gCompare x y = compare (ctorIndex x) (ctorIndex y)+ <> mzipWith @Ord compare x y+{-# INLINE gCompare #-}++-- | '<=' implemented by using '<=' between all of the components. First+-- compares constructors.+gLTE+ :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> Bool+gLTE x y = not $ gGT x y+{-# INLINE gLTE #-}++-- | '<' implemented by using '<' between all of the components. First+-- compares constructors.+gLT :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> Bool+gLT x y = ctorIndex x < ctorIndex y+ || getAny (mzipWith @Ord (\x' -> Any . (x' <)) x y)+{-# INLINE gLT #-}++-- | '>=' implemented by using '>=' between all of the components. First+-- compares constructors.+gGTE+ :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> Bool+gGTE x y = not $ gLT x y+{-# INLINE gGTE #-}++-- | '>' implemented by using '>' between all of the components. First+-- compares constructors.+gGT :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> Bool+gGT x y = ctorIndex x > ctorIndex y+ || getAny (mzipWith @Ord (\x' -> Any . (x' >)) x y)+{-# INLINE gGT #-}++-- | 'max' implemented by using 'max' between all of the components. First+-- compares constructors. If two items are equal, returns the second.+gMax+ :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> a+gMax x y | gLTE x y = y+ | otherwise = x+{-# INLINE gMax #-}++-- | 'min' implemented by using 'min' between all of the components. First+-- compares constructors. If two items are equal, returns the first.+gMin+ :: forall a. (ADT a, Constraints a Ord)+ => a -> a -> a+gMin x y | gLTE x y = x+ | otherwise = y+{-# INLINE gMin #-}+
+ src/Generics/OneLiner/Instances/Internal.hs view
@@ -0,0 +1,22 @@++module Generics.OneLiner.Instances.Internal (+ c0+ , c1+ , c2+ , c2'+ ) where++import Data.Coerce++c0 :: Coercible a b => b -> a+c0 = coerce++c1 :: Coercible a b => (b -> b) -> a -> a+c1 f = coerce . f . coerce++c2 :: Coercible a b => (b -> b -> b) -> a -> a -> a+c2 f x y = coerce (f (coerce x) (coerce y))++c2' :: Coercible a b => (b -> b -> c) -> a -> a -> c+c2' f x y = f (coerce x) (coerce y)+
src/Numeric/OneLiner.hs view
@@ -25,12 +25,10 @@ -- or 'Floating', depending on the function). -- -- Also includes a newtype wrapper that imbues any such data type with an--- instant 'Num' (and 'Fractional' and 'Floating') instance.------ See README for details on usage instructions and motivations.+-- instant 'Num' (and 'Fractional' and 'Floating') instance, which can one+-- day be used with /DerivingVia/ syntax to derive instances automatically. -- - module Numeric.OneLiner ( -- * Newtype wrapper GNum(..)@@ -72,6 +70,7 @@ import Data.Data import GHC.Generics import Generics.OneLiner+import Generics.OneLiner.Instances.Internal -- | If @a@ is a data type with a single constructor whose fields are all -- instances of 'Num', then @'GNum' a@ has a 'Num' instance.@@ -82,45 +81,83 @@ -- If @a@ is a data type with a single constructor whose fields are all -- instances of 'Floating', then @'GNum' a@ has a 'Floating' instance. --+-- Will one day be able to be used with /DerivingVia/ syntax, to derive+-- instances automatically.+-- newtype GNum a = GNum { getGNum :: a } deriving (Eq, Ord, Show, Read, Data, Generic, Functor, Foldable, Traversable) -instance (ADTRecord a, Constraints (GNum a) Num)+instance (ADTRecord a, Constraints a Num) => Num (GNum a) where- (+) = gPlus- (-) = gMinus- (*) = gTimes- negate = gNegate- abs = gAbs- signum = gSignum- fromInteger = gFromInteger+ (+) = c2 (gPlus @a)+ {-# INLINE (+) #-}+ (-) = c2 (gMinus @a)+ {-# INLINE (-) #-}+ (*) = c2 (gTimes @a)+ {-# INLINE (*) #-}+ negate = c1 (gNegate @a)+ {-# INLINE negate #-}+ abs = c1 (gAbs @a)+ {-# INLINE abs #-}+ signum = c1 (gSignum @a)+ {-# INLINE signum #-}+ fromInteger = c0 (gFromInteger @a)+ {-# INLINE fromInteger #-} -instance (ADTRecord a, Constraints (GNum a) Fractional)+instance ( ADTRecord a+ , Constraints a Num+ , Constraints a Fractional+ ) => Fractional (GNum a) where- (/) = gDivide- recip = gRecip- fromRational = gFromRational+ (/) = c2 (gDivide @a)+ {-# INLINE (/) #-}+ recip = c1 (gRecip @a)+ {-# INLINE recip #-}+ fromRational = c0 (gFromRational @a)+ {-# INLINE fromRational #-} -instance (ADTRecord a, Constraints (GNum a) Floating)+instance ( ADTRecord a+ , Constraints a Num+ , Constraints a Fractional+ , Constraints a Floating+ ) => Floating (GNum a) where- pi = gPi- exp = gExp- log = gLog- sqrt = gSqrt- (**) = gPower- logBase = gLogBase- sin = gSin- cos = gCos- tan = gTan- asin = gAsin- acos = gAcos- atan = gAtan- sinh = gSinh- cosh = gCosh- tanh = gTanh- asinh = gAsinh- acosh = gAcosh- atanh = gAtanh+ pi = c0 (gPi @a)+ {-# INLINE pi #-}+ exp = c1 (gExp @a)+ {-# INLINE exp #-}+ log = c1 (gLog @a)+ {-# INLINE log #-}+ sqrt = c1 (gSqrt @a)+ {-# INLINE sqrt #-}+ (**) = c2 (gPower @a)+ {-# INLINE (**) #-}+ logBase = c2 (gLogBase @a)+ {-# INLINE logBase #-}+ sin = c1 (gSin @a)+ {-# INLINE sin #-}+ cos = c1 (gCos @a)+ {-# INLINE cos #-}+ tan = c1 (gTan @a)+ {-# INLINE tan #-}+ asin = c1 (gAsin @a)+ {-# INLINE asin #-}+ acos = c1 (gAcos @a)+ {-# INLINE acos #-}+ atan = c1 (gAtan @a)+ {-# INLINE atan #-}+ sinh = c1 (gSinh @a)+ {-# INLINE sinh #-}+ cosh = c1 (gCosh @a)+ {-# INLINE cosh #-}+ tanh = c1 (gTanh @a)+ {-# INLINE tanh #-}+ asinh = c1 (gAsinh @a)+ {-# INLINE asinh #-}+ acosh = c1 (gAcosh @a)+ {-# INLINE acosh #-}+ atanh = c1 (gAtanh @a)+ {-# INLINE atanh #-} -- $num -- All of these implement the appropriate functions by carrying them over@@ -130,139 +167,167 @@ :: forall a. (ADTRecord a, Constraints a Num) => a -> a -> a gPlus = binaryOp @Num (+)+{-# INLINE gPlus #-} gMinus :: forall a. (ADTRecord a, Constraints a Num) => a -> a -> a gMinus = binaryOp @Num (-)+{-# INLINE gMinus #-} gTimes :: forall a. (ADTRecord a, Constraints a Num) => a -> a -> a gTimes = binaryOp @Num (*)+{-# INLINE gTimes #-} gNegate :: forall a. (ADTRecord a, Constraints a Num) => a -> a gNegate = unaryOp @Num negate+{-# INLINE gNegate #-} gAbs :: forall a. (ADTRecord a, Constraints a Num) => a -> a gAbs = unaryOp @Num abs+{-# INLINE gAbs #-} gSignum :: forall a. (ADTRecord a, Constraints a Num) => a -> a gSignum = unaryOp @Num signum+{-# INLINE gSignum #-} gFromInteger :: forall a. (ADTRecord a, Constraints a Num) => Integer -> a gFromInteger x = nullaryOp @Num (fromInteger x)+{-# INLINE gFromInteger #-} gDivide :: forall a. (ADTRecord a, Constraints a Fractional) => a -> a -> a gDivide = binaryOp @Fractional (/)+{-# INLINE gDivide #-} gRecip :: forall a. (ADTRecord a, Constraints a Fractional) => a -> a gRecip = unaryOp @Fractional recip+{-# INLINE gRecip #-} gFromRational :: forall a. (ADTRecord a, Constraints a Fractional) => Rational -> a gFromRational x = nullaryOp @Fractional (fromRational x)+{-# INLINE gFromRational #-} gPi :: forall a. (ADTRecord a, Constraints a Floating) => a gPi = nullaryOp @Floating pi+{-# INLINE gPi #-} gExp :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gExp = unaryOp @Floating exp+{-# INLINE gExp #-} gLog :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gLog = unaryOp @Floating log+{-# INLINE gLog #-} gSqrt :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gSqrt = unaryOp @Floating sqrt+{-# INLINE gSqrt #-} gPower :: forall a. (ADTRecord a, Constraints a Floating) => a -> a -> a gPower = binaryOp @Floating (**)+{-# INLINE gPower #-} gLogBase :: forall a. (ADTRecord a, Constraints a Floating) => a -> a -> a gLogBase = binaryOp @Floating logBase+{-# INLINE gLogBase #-} gSin :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gSin = unaryOp @Floating sin+{-# INLINE gSin #-} gCos :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gCos = unaryOp @Floating cos+{-# INLINE gCos #-} gTan :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gTan = unaryOp @Floating tan+{-# INLINE gTan #-} gAsin :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAsin = unaryOp @Floating asin+{-# INLINE gAsin #-} gAcos :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAcos = unaryOp @Floating acos+{-# INLINE gAcos #-} gAtan :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAtan = unaryOp @Floating atan+{-# INLINE gAtan #-} gSinh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gSinh = unaryOp @Floating sinh+{-# INLINE gSinh #-} gCosh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gCosh = unaryOp @Floating cosh+{-# INLINE gCosh #-} gTanh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gTanh = unaryOp @Floating atanh+{-# INLINE gTanh #-} gAsinh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAsinh = unaryOp @Floating asinh+{-# INLINE gAsinh #-} gAcosh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAcosh = unaryOp @Floating acosh+{-# INLINE gAcosh #-} gAtanh :: forall a. (ADTRecord a, Constraints a Floating) => a -> a gAtanh = unaryOp @Floating atanh+{-# INLINE gAtanh #-}