on dff2daf help sign in
.github/workflows/ci.yaml+13−7
since splitsnapshots
unifiedsplit
@@ -4,14 +4,20 @@ on:
4 push:
4 push:
5jobs:
5jobs:
6 build:
6 build:
7+ runs-on: ${{ matrix.os }}
8+ strategy:
9+ matrix:
10+ ghc: ['ghc884', 'ghc8101']
7− runs-on: ubuntu-latest
11+ os: [ubuntu-latest]
12+ name: GHC ${{ matrix.ghc }}
8 steps:
13 steps:
9 - uses: actions/checkout@v2
14 - uses: actions/checkout@v2
10− - uses: nixbuild/nix-quick-install-action@v21
15+ - uses: cachix/install-nix-action@v10
16+ - uses: cachix/cachix-action@v6
11 with:
17 with:
12− nix_conf: |
18+ name: juspay-nau
13− experimental-features = nix-command flakes
19+ signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
20+ # Only needed for private caches
21+ authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
14 - name: Build and test 🔧
22 - name: Build and test 🔧
15− run: nix build -j 4 -L
23+ run: nix-build -j4 --argstr compiler ${{ matrix.ghc }}
16− - name: Build and test (GHC 8.8) 🔧
17− run: nix build -j 4 -L .#jrec-ghc88
.vscode/extensions.jsondeleted−11
@@ -1,11 +0,0 @@
1−{
2− // See https://go.microsoft.com/fwlink/?LinkId=827846
3− // for the documentation about the extensions.json format
4− "recommendations": [
5− "haskell.haskell",
6− "arrterian.nix-env-selector",
7− "bbenoist.nix",
8− "jnoortheen.nix-ide",
9− "tamasfe.even-better-toml"
10− ]
11−}
.vscode/settings.json+4−5
@@ -1,6 +1,5 @@
1{
1{
2− "editor.formatOnType": true,
3− "editor.formatOnSave": true,
4− "nixEnvSelector.nixFile": "${workspaceRoot}/shell.nix",
2+ "nixEnvSelector.nixShellConfig": "${workspaceRoot}/default.nix",
5− "haskell.manageHLS": "PATH"
3+ "editor.formatOnType": true,
4+ "editor.formatOnSave": true
6−}
5+}
CHANGELOG.md−4
@@ -1,9 +1,5 @@
1# Revision history for rec
1# Revision history for rec
2
2
3−## Unreleased
4−
5−- GHC 9.2 + Aeson 2.0 support
6−
7## 0.1.0.0 -- YYYY-mm-dd
3## 0.1.0.0 -- YYYY-mm-dd
8
4
9* First version. Released on an unsuspecting world.
5* First version. Released on an unsuspecting world.
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
bin/test+1−1
@@ -2,4 +2,4 @@
2set -xe
2set -xe
3
3
4# NOTE: ghcid should be run with -W to allow warnings from should-not-typecheck
4# NOTE: ghcid should be run with -W to allow warnings from should-not-typecheck
5−nix develop -c sh -c "ghcid $* -W -c 'cabal new-repl test:jrec-test' -T \":main $*\""
5+nix-shell --pure --run "ghcid $* -W -c 'cabal new-repl test:jrec-test' -T \":main $*\""
default.nixnew file+36
@@ -0,0 +1,36 @@
1+let
2+ nixpkgsSrc = builtins.fetchTarball {
3+ url = "https://github.com/nixos/nixpkgs/archive/76f2e271a2ef.tar.gz";
4+ sha256 = "1r4da3kyghqq7vzya5yb295jpnha1fgp755bi6wda4fmhyaynnsp";
5+ };
6+ gitignoreSrc = builtins.fetchTarball {
7+ url = "https://github.com/hercules-ci/gitignore/archive/c4662e6.tar.gz";
8+ sha256 = "1npnx0h6bd0d7ql93ka7azhj40zgjp815fw2r6smg8ch9p7mzdlx";
9+ };
10+ inherit (import gitignoreSrc { inherit (pkgs); }) gitignoreSource;
11+in {
12+ compiler ? "default",
13+ pkgs ? import nixpkgsSrc {},
14+}:
15+ let
16+ haskellPackages =
17+ if compiler == "default"
18+ then pkgs.haskellPackages
19+ else pkgs.haskell.packages.${compiler};
20+ projectDrv =
21+ haskellPackages.override {
22+ overrides = self: super: with pkgs.haskell.lib; {
23+ jrec = self.callCabal2nix "jrec" (gitignoreSource ./.) {};
24+ # https://github.com/lspitzner/data-tree-print/pull/2
25+ data-tree-print = doJailbreak super.data-tree-print;
26+ };
27+ };
28+ projectShell =
29+ projectDrv.shellFor {
30+ packages = p: [ p.jrec ];
31+ buildInputs = with projectDrv; [
32+ cabal-install
33+ ];
34+ };
35+ in
36+ if pkgs.lib.inNixShell then projectShell else projectDrv.jrec
flake.lockdeleted−81
@@ -1,81 +0,0 @@
1−{
2− "nodes": {
3− "flake-parts": {
4− "inputs": {
5− "nixpkgs-lib": "nixpkgs-lib"
6− },
7− "locked": {
8− "lastModified": 1678379998,
9− "narHash": "sha256-TZdfNqftHhDuIFwBcN9MUThx5sQXCTeZk9je5byPKRw=",
10− "owner": "hercules-ci",
11− "repo": "flake-parts",
12− "rev": "c13d60b89adea3dc20704c045ec4d50dd964d447",
13− "type": "github"
14− },
15− "original": {
16− "owner": "hercules-ci",
17− "repo": "flake-parts",
18− "type": "github"
19− }
20− },
21− "nixpkgs": {
22− "locked": {
23− "lastModified": 1678594102,
24− "narHash": "sha256-OHAHYiMWJFPNxuW/PcOMlSD2tvXnEYC1jxREBADHwwQ=",
25− "owner": "nixos",
26− "repo": "nixpkgs",
27− "rev": "796b4a3c1d903c4b9270cd2548fe46f524eeb886",
28− "type": "github"
29− },
30− "original": {
31− "owner": "nixos",
32− "ref": "nixpkgs-unstable",
33− "repo": "nixpkgs",
34− "type": "github"
35− }
36− },
37− "nixpkgs-ghc88": {
38− "locked": {
39− "lastModified": 1596466290,
40− "narHash": "sha256-V1vrlYfVEdW4iauUc58LCtorSxLLF+X/PhjD5+dQjeQ=",
41− "owner": "nixos",
42− "repo": "nixpkgs",
43− "rev": "76f2e271a2ef9de3734dcc9d366a42d6bfb18e82",
44− "type": "github"
45− },
46− "original": {
47− "owner": "nixos",
48− "ref": "76f2e271a2ef",
49− "repo": "nixpkgs",
50− "type": "github"
51− }
52− },
53− "nixpkgs-lib": {
54− "locked": {
55− "dir": "lib",
56− "lastModified": 1678375444,
57− "narHash": "sha256-XIgHfGvjFvZQ8hrkfocanCDxMefc/77rXeHvYdzBMc8=",
58− "owner": "NixOS",
59− "repo": "nixpkgs",
60− "rev": "130fa0baaa2b93ec45523fdcde942f6844ee9f6e",
61− "type": "github"
62− },
63− "original": {
64− "dir": "lib",
65− "owner": "NixOS",
66− "ref": "nixos-unstable",
67− "repo": "nixpkgs",
68− "type": "github"
69− }
70− },
71− "root": {
72− "inputs": {
73− "flake-parts": "flake-parts",
74− "nixpkgs": "nixpkgs",
75− "nixpkgs-ghc88": "nixpkgs-ghc88"
76− }
77− }
78− },
79− "root": "root",
80− "version": 7
81−}
flake.nixdeleted−34
@@ -1,34 +0,0 @@
1−{
2− inputs = {
3− nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
4− nixpkgs-ghc88.url = "github:nixos/nixpkgs/76f2e271a2ef";
5− flake-parts.url = "github:hercules-ci/flake-parts";
6− };
7− outputs = inputs@{ nixpkgs, flake-parts, ... }:
8− flake-parts.lib.mkFlake { inherit inputs; } {
9− systems = nixpkgs.lib.systems.flakeExposed;
10− perSystem = { self', inputs', pkgs, system, ... }:
11− let
12− overlay = self: super: {
13− jrec = self.callCabal2nix "jrec" ./. { };
14− };
15− ghcVersions = {
16− ghc88 = inputs.nixpkgs-ghc88.legacyPackages.${system}.haskellPackages.extend overlay;
17− ghc92 = pkgs.haskellPackages.extend overlay;
18− };
19− in
20− {
21− packages.default = ghcVersions.ghc92.jrec;
22− devShells.default = ghcVersions.ghc92.shellFor {
23− packages = p: [ p.jrec ];
24− buildInputs = with ghcVersions.ghc92; [
25− cabal-install
26− ghcid
27− haskell-language-server
28− ];
29− };
30− # Expose jrec built with GHC 8.8 so it can be tested in CI.
31− packages.jrec-ghc88 = ghcVersions.ghc88.jrec;
32− };
33− };
34−}
jrec.cabal+2−5
@@ -1,6 +1,6 @@
1cabal-version: 2.4
1cabal-version: 2.4
2name: jrec
2name: jrec
3−version: 0.1.0.1
3+version: 0.1.0.0
4synopsis: anonymous records for busy people
4synopsis: anonymous records for busy people
5
5
6-- description:
6-- description:
@@ -37,7 +37,7 @@ common library-common
37 default-language: Haskell2010
37 default-language: Haskell2010
38 build-depends:
38 build-depends:
39 aeson
39 aeson
40− , base >=4.13 && <4.17
40+ , base >=4.13 && <4.15
41 , constraints
41 , constraints
42 , deepseq
42 , deepseq
43 , generic-data
43 , generic-data
@@ -97,9 +97,6 @@ test-suite jrec-test
97 hs-source-dirs: test, src
97 hs-source-dirs: test, src
98 main-is: Spec.hs
98 main-is: Spec.hs
99 cpp-options: -DWITH_AESON -DWITH_GENERICS
99 cpp-options: -DWITH_AESON -DWITH_GENERICS
100− other-modules:
101− JRecShouldNotTypecheckSpec
102− JRecSpec
103 build-depends:
100 build-depends:
104 base,
101 base,
105 hspec,
102 hspec,
shell.nixdeleted−1
@@ -1 +0,0 @@
1−(builtins.getFlake ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default
src/JRec/Internal.hs+11−17
@@ -32,7 +32,6 @@ import qualified Control.Monad.State as S
32import Data.Aeson
32import Data.Aeson
33import Data.Aeson.Types (Parser)
33import Data.Aeson.Types (Parser)
34import Data.Constraint
34import Data.Constraint
35−import Data.List (intercalate)
36import Data.Maybe (catMaybes)
35import Data.Maybe (catMaybes)
37import Data.Proxy
36import Data.Proxy
38import qualified Data.Text as T
37import qualified Data.Text as T
@@ -43,17 +42,11 @@ import GHC.OverloadedLabels
43import GHC.Prim
42import GHC.Prim
44import GHC.ST (ST (..), runST)
43import GHC.ST (ST (..), runST)
45import GHC.TypeLits
44import GHC.TypeLits
45+import Generic.Data (gshowsPrec)
46+import Generic.Data.Internal.Show (GShow)
46import qualified Optics.Lens as OL
47import qualified Optics.Lens as OL
47import Unsafe.Coerce
48import Unsafe.Coerce
48import Prelude
49import Prelude
49−#if MIN_VERSION_aeson(2,0,0)
50−import Data.Aeson.Key (fromText, fromString)
51−#else
52−fromText :: a -> a
53−fromText = id
54−fromString :: String -> T.Text
55−fromString = T.pack
56−#endif
57
50
58-- | Field named @l@ labels value of type @t@ adapted from the awesome /labels/ package.
51-- | Field named @l@ labels value of type @t@ adapted from the awesome /labels/ package.
59-- Example: @(#name := \"Chris\") :: (\"name\" := String)@
52-- Example: @(#name := \"Chris\") :: (\"name\" := String)@
@@ -109,12 +102,13 @@ defaultJSONOptions = JSONOptions {fieldTransform = id}
109type role Rec representational
102type role Rec representational
110
103
111instance
104instance
112− ( RecApply lts lts Show
105+ ( RecApply lts lts Show,
106+ GShow Proxy (Rep (Rec lts)),
107+ Generic (Rec lts)
113 ) =>
108 ) =>
114 Show (Rec lts)
109 Show (Rec lts)
115 where
110 where
116− show rec = "{" ++ formatted ++ "}"
111+ show = (\x -> if null x then "{}" else x) . unwords . drop 1 . words . flip (gshowsPrec 0) ""
117− where formatted = intercalate ", " $ map (\(k, v) -> k ++ " = " ++ v) $ showRec rec
118
112
119instance RecEq lts lts => Eq (Rec lts) where
113instance RecEq lts lts => Eq (Rec lts) where
120 (==) (a :: Rec lts) (b :: Rec lts) = recEq a b (Proxy :: Proxy lts)
114 (==) (a :: Rec lts) (b :: Rec lts) = recEq a b (Proxy :: Proxy lts)
@@ -566,16 +560,16 @@ class ToJSON a => EncodeField a where
566
560
567instance ToJSON a => EncodeField a where
561instance ToJSON a => EncodeField a where
568 encodeField = pure . toJSON
562 encodeField = pure . toJSON
569− encodeKV k v = fromText k .= v
563+ encodeKV = (.=)
570
564
571instance {-# OVERLAPS #-} ToJSON a => EncodeField (Maybe a) where
565instance {-# OVERLAPS #-} ToJSON a => EncodeField (Maybe a) where
572 encodeField = fmap toJSON
566 encodeField = fmap toJSON
573 encodeKV _ Nothing = mempty
567 encodeKV _ Nothing = mempty
574− encodeKV k v = fromText k .= v
568+ encodeKV k v = k .= v
575
569
576recToValue :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Value
570recToValue :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Value
577recToValue options r =
571recToValue options r =
578− object $ catMaybes $ reflectRec @EncodeField Proxy (\k v -> (fromString (fieldTransform options k),) <$> encodeField v) r
572+ object $ catMaybes $ reflectRec @EncodeField Proxy (\k v -> (T.pack (fieldTransform options k),) <$> encodeField v) r
579
573
580recToEncoding :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Encoding
574recToEncoding :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Encoding
581recToEncoding options r =
575recToEncoding options r =
@@ -680,10 +674,10 @@ class FromJSON a => ParseField a where
680 parseField :: Object -> T.Text -> Parser a
674 parseField :: Object -> T.Text -> Parser a
681
675
682instance FromJSON a => ParseField a where
676instance FromJSON a => ParseField a where
683− parseField o k = o .: fromText k
677+ parseField = (.:)
684
678
685instance {-# OVERLAPS #-} FromJSON a => ParseField (Maybe a) where
679instance {-# OVERLAPS #-} FromJSON a => ParseField (Maybe a) where
686− parseField o k = o .:? fromText k
680+ parseField = (.:?)
687
681
688instance
682instance
689 ( KnownSymbol l,
683 ( KnownSymbol l,