derivingvia-extras (empty) → 0.1.0.0
raw patch · 6 files changed
+185/−0 lines, 6 filesdep +basedep +hashablesetup-changed
Dependencies added: base, hashable
Files
- CHANGELOG.md +5/−0
- LICENSE +30/−0
- README.md +39/−0
- Setup.hs +2/−0
- derivingvia-extras.cabal +43/−0
- src/Deriving/On.hs +66/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for derivingvia-extras++## 0.1.0.0 -- 2022-04-29++* First version. Added `On` for deriving non-structural instances on a particular record field.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2022, Baldur Blöndal++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Baldur Blöndal nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,39 @@+# derivingvia-extras++Miscellaneous via types, for use with `DerivingVia`.++## `On`++The type `On T "field"` derives non-structural instances for `T` by+comparing an evaluting it only at the record field `"field"`.++```haskell+{-# Language DataKinds #-}+{-# Language DerivingVia #-}+{-# Language TypeOperators #-}++import Deriving.On+import Data.Hashable++data User = User+ { name :: String+ , age :: Int+ , userID :: Integer+ }+ deriving (Eq, Ord, Hashable)+ via User `On` "userID"+```++such that all other fields are ignored++```haskell+>> alice = User "Alice" 50 0xDEADBEAF+>> bob = User "Bob" 20 0xDEADBEAF+>>+>> alice == bob+True+>> alice <= bob+True+>> hash alice == hash bob+True+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ derivingvia-extras.cabal view
@@ -0,0 +1,43 @@+cabal-version: 2.0+name: derivingvia-extras+build-type: Simple+version: 0.1.0.0+license: BSD3+license-file: LICENSE+category: Deriving, Utils+author: Baldur Blöndal+maintainer: Baldur Blöndal+bug-reports: https://github.com/Icelandjack/derivingvia-extras/issues+synopsis: DerivingVia extras - Miscellaneous /via/ types.+extra-source-files:+ CHANGELOG.md+ README.md+description:+ Includes various functionality to use with 'DerivingVia'.+ .+ > -- >> alice = User "Alice" 50 0xDEADBEAF+ > -- >> bob = User "Bob" 20 0xDEADBEAF+ > -- >>+ > -- >> alice == bob+ > -- True+ > -- >> hash alice == hash bob+ > -- True+ > data User = User+ > { name :: String+ > , age :: Int+ > , userID :: Integer+ > }+ > deriving (Eq, Ord, Hashable)+ > via User `On` "userID"++source-repository head+ type: git+ location: https://github.com/Icelandjack/derivingvia-extras++library+ exposed-modules:+ Deriving.On+ hs-source-dirs: src+ default-language: Haskell98+ build-depends:+ base == 4.*, hashable -any
+ src/Deriving/On.hs view
@@ -0,0 +1,66 @@+{-# Language DataKinds #-}+{-# Language InstanceSigs #-}+{-# Language ScopedTypeVariables #-}+{-# Language StandaloneKindSignatures #-}+{-# Language TypeApplications #-}+{-# Language TypeOperators #-}+{-# Language UndecidableInstances #-}++module Deriving.On (On(..)) where++import Data.Function (on)+import Data.Hashable (Hashable(..))+import Data.Kind (Type)+import Data.Ord (comparing)+import GHC.Records (HasField(..))+import GHC.TypeLits (Symbol)++-- | With 'DerivingVia': to derive non-structural instances. Specifies+-- what field to base instances on.+--+-- The type @'On' User "userID"@ is compared and evaluated based only+-- on the @"userID"@ record field. This uses 'HasField' from+-- @GHC.Records@ to project the relevant component.+--+-- @+-- {-# Language DataKinds #-}+-- {-# Language DerivingVia #-}+-- {-# Language TypeOperators #-}+--+-- import Deriving.On+-- import Data.Hashable+--+-- data User = User+-- { name :: String+-- , age :: Int+-- , userID :: Integer+-- }+-- deriving (Eq, Ord, Hashable)+-- via User `On` "userID"+-- @+--+-- @+-- >> alice = User "Alice" 50 0xDEADBEAF+-- >> bob = User "Bob" 20 0xDEADBEAF+-- >>+-- >> alice == bob+-- True+-- >> alice <= bob+-- True+-- >> hash alice == hash bob+-- True+-- @+type On :: Type -> Symbol -> Type+newtype a `On` field = On a++instance (HasField field a b, Eq b) => Eq (a `On` field) where+ (==) :: a `On` field -> a `On` field -> Bool+ On a1 == On a2 = ((==) `on` getField @field) a1 a2++instance (HasField field a b, Ord b) => Ord (a `On` field) where+ compare :: a `On` field -> a `On` field -> Ordering+ On a1 `compare` On a2 = comparing (getField @field) a1 a2++instance (HasField field a b, Hashable b) => Hashable (a `On` field) where+ hashWithSalt :: Int -> a `On` field -> Int+ hashWithSalt salt (On a) = hashWithSalt salt (getField @field a)