packages feed

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 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 #-}