Skip to content

Commit

Permalink
Make surgeries first-class at the type level
Browse files Browse the repository at this point in the history
  • Loading branch information
Lysxia committed Jun 21, 2020
1 parent b785417 commit 3e5f1d9
Show file tree
Hide file tree
Showing 7 changed files with 587 additions and 167 deletions.
1 change: 1 addition & 0 deletions examples/example-aeson.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
TypeApplications #-}

import Data.Aeson
import Data.Aeson.Types (omitNothingFields)
import GHC.Generics (Generic)
import Generic.Data.Surgery (fromOR, toOR', modifyRField)

Expand Down
18 changes: 18 additions & 0 deletions generic-data-surgery.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ test-suite surgery-test
default-language: Haskell2010
type: exitcode-stdio-1.0

test-suite synthetic-test
hs-source-dirs: test
main-is: synthetic.hs
build-depends:
tasty,
tasty-hunit,
generic-data,
generic-data-surgery,
show-combinators >= 0.2,
-- ^ avoid a bug
base
if !impl(ghc >= 8.6)
build-depends:
contravariant
ghc-options: -Wall
default-language: Haskell2010
type: exitcode-stdio-1.0

source-repository head
type: git
location: https://github.com/Lysxia/generic-data-surgery
48 changes: 44 additions & 4 deletions src/Generic/Data/Surgery.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,64 @@ module Generic.Data.Surgery
--
-- Note that @()@ and 'Data.Functor.Identity.Identity' can be used as an
-- empty and a singleton tuple type respectively.

, removeConstr
, insertConstr
, modifyConstr

-- *** Constructors as tuples
--
-- When the tuple type can't be inferred and doesn't really matter,
-- an alternative to explicit type annotations is to use the @...ConstrT@
-- variants of these surgeries, which are specialized to actual tuples
-- (@()@, 'Data.Functor.Identity.Identity', @(,)@, @(,,)@, up to 7 ---
-- because that's where 'GHC.Generics.Generic' instances currently stop).

, removeConstr
, insertConstr
, modifyConstr
, removeConstrT
, insertConstrT
, modifyConstrT

-- * Surgeries as type-level operations

-- | Example usage: define a synthetic type which adds a @\"key\"@ field of type @Key@
-- to an existing record type.
--
-- @
-- -- Define the surgery to insert a field (key :: Key)
-- -- as the first field (index 0) of a record.
-- type InsertId = ('InsertField' 0 (''Just' \"key\") Key :: 'MajorSurgery' k)
--
-- -- Define a newtype for synthetic ('Data') types obtained from a real type @a@
-- -- using the @InsertId@ surgery we just defined.
-- newtype WithKey a = WithKey ('Data' ('Operate' ('GHC.Generics.Rep' a) InsertId) ())
-- @

-- ** Types and composition

-- |
-- === Implementation notes
--
-- The implementation of these type synonyms is hidden behind names
-- suffixed with an underscore. Although they appear in the haddocks,
-- these auxiliary names are internal and not exported by this module.

, MajorSurgery
, Perform
, Operate
, (:>>)
, IdSurgery

-- ** Surgeries
, InsertField
, RemoveField
, RemoveRField
, InsertConstrAt
, RemoveConstr
, Suture

-- * Constraint synonyms

-- | Hiding implementation details from the signatures above.
-- Useful to compose surgeries in a reusable way.

-- ** Conversions

Expand Down
Loading

0 comments on commit 3e5f1d9

Please sign in to comment.