it-has: Automatically derivable Has instances.

[ bsd3, data, library ] [ Propose Tags ]

Please see the README on GitHub at https://github.com/dnikolovv/it-has#readme


[Skip to Readme]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.2.0.0
Change log ChangeLog.md
Dependencies base (>=4.7 && <5), generic-lens (==2.0.0.0) [details]
License BSD-3-Clause
Copyright Dobromir Nikolov
Author Dobromir Nikolov
Maintainer dnikolovv@hotmail.com
Category Data
Home page https://github.com/dnikolovv/it-has#readme
Bug tracker https://github.com/dnikolovv/it-has/issues
Source repo head: git clone https://github.com/dnikolovv/it-has
Uploaded by dnikolovv at 2020-05-18T05:40:27Z
Distributions
Downloads 499 total (2 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2020-05-18 [all 1 reports]

Readme for it-has-0.2.0.0

[back to package description]

Hackage Haskell CI

it-has

This is a (nearly) drop-in replacement of data-has. The differences with the original package are that this one misses hasLens and uses Generic for its default implementation. Your initial reaction may be to start mourning the loss of hasLens, but first take a look at the cool things you can do without it!

Reduce boilerplate! You can trim down this:

data Config =
  Config
    { configLogEnv      :: !LogEnv
    , configJwtSettings :: !JWTSettings
    , configMetrics     :: !Metrics
    , configEkgStore    :: !EKG.Store }

-- Heavy manual instances, data-has only has default implementation for tuples
instance Has LogEnv Config where
  getter = configLogEnv
  modifier f v = v { configLogEnv = f (configLogEnv v) }

instance Has JWTSettings Config where
  getter = configJwtSettings
  modifier f v = v { configJwtSettings = f (configJwtSettings v) }

instance Has Metrics Config where
  getter = configMetrics
  modifier f v = v { configMetrics = f (configMetrics v) }

instance Has EKG.Store Config where
  getter = configEkgStore
  modifier f v = v { configEkgStore = f (configEkgStore v) }

To this:

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric  #-}

data Config =
  Config
    { configLogEnv      :: !LogEnv
    , configJwtSettings :: !JWTSettings
    , configMetrics     :: !Metrics
    , configEkgStore    :: !EKG.Store
    } deriving (Generic, Has LogEnv, Has JWTSettings, Has Metrics, Has EKG.Store)

Another trick is that you can "force" a sum type to have a specific field defined.

E.g. you may want to define an Error type and enforce that it always has an ErrorText attached to it.

newtype ErrorText =
 ErrorText Text
 
data Error =
 ValidationError |
 NotFound |
 Critical |
 Unauthorized

You can do that by deriving Has ErrorText. The compiler will error until you have added an ErrorText field to each representation.

data Error =
 ValidationError ErrorText |
 NotFound ErrorText |
 Critical ErrorText |
 Unauthorized ErrorText
 deriving (Generic, Has ErrorText)

For more documentation and examples, please refer to the original package.