Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Rework #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ Run `bin/test` for fast-reloading tests. When library sources change, the test s
* Documentation.
* Expose all internals.
* `-- NOTE: doesn't use 'KeyDoesNotExist'` — fix this.
* `RemoveAccessTo` — can we get rid of it?

## Acknowledgement

Expand Down
8 changes: 6 additions & 2 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
import Distribution.Simple
main = defaultMain
module Main where

import Distribution.Extra.Doctest (defaultMainWithDoctests)

main :: IO ()
main = defaultMainWithDoctests "doctests"
12 changes: 6 additions & 6 deletions bin/genrecord
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ main = do
putStrLn
"-- Generated with cabal run -v0 bin/genrecord > src/JRec/Tuple.hs\n\
\\n\
\{-# LANGUAGE TypeOperators, DataKinds, FlexibleInstances, MultiParamTypeClasses #-}\n\
\{-# LANGUAGE FunctionalDependencies, GADTs, UndecidableInstances #-}\n\
\\n\
\module JRec.Tuple where\n\
\\n\
\import qualified JRec.Internal as R\n\
Expand Down Expand Up @@ -46,10 +49,7 @@ genInstance i =
exprList
exprTuple
constraints =
tupleF $
format "R.RecApply {} {} R.NoConstraint" typeList typeList :
[format "n{} ~ n{}'" j j :: Builder | j <- [1 .. i]]
++ [format "v{} ~ v{}'" j j :: Builder | j <- [1 .. i]]
tupleF [format "(n{} R.:= v{}) ~ f{}" j j j :: Builder | j <- [1 .. i]]
in format
"instance {} => RecTuple {} {} where\n\
\ {}\n\
Expand All @@ -61,8 +61,8 @@ genInstance i =
fromTuple
toTuple
where
-- '[n1' R.:= v1', n2' R.:= v2']
typeList = "'" <> listF [format "n{}' R.:= v{}'" j j :: Builder | j <- [1 .. i]]
-- '[f1, f2]
typeList = "'" <> listF ["f" <> show j | j <- [1 .. i]]
-- (n1 R.:= v1, n2 R.:= v2)
typeTuple = tupleF [format "n{} R.:= v{}" j j :: Builder | j <- [1 .. i]]
-- (f1, f2)
Expand Down
3 changes: 1 addition & 2 deletions bin/test
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -xe

# NOTE: ghcid should be run with -W to allow warnings from should-not-typecheck
nix-shell --pure --run "ghcid $* -W -c 'cabal new-repl test:jrec-test' -T \":main $*\""
nix-shell --pure --run "ghcid $* -c 'cabal new-repl test:jrec-test' -T \":main $*\""
3 changes: 3 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ in {
packages = p: [ p.jrec ];
buildInputs = with projectDrv; [
cabal-install
ormolu
haskell-language-server
ghcid
];
};
in
Expand Down
57 changes: 24 additions & 33 deletions jrec.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ maintainer: artyom.kazak@juspay.in

-- copyright:
-- category:
build-type: Simple
build-type: Custom
extra-source-files:
CHANGELOG.md
README.md

custom-setup
setup-depends:
base
, Cabal
, cabal-doctest >=1.0.8 && <1.1

flag with-aeson
description: Enable Aeson instances
-- don't let the solver fiddle with the flag
Expand All @@ -41,34 +47,6 @@ common library-common
, lens
, mtl
, text
default-extensions:
BlockArguments
DataKinds
DeriveGeneric
DerivingStrategies
DuplicateRecordFields
FlexibleContexts
FlexibleInstances
FunctionalDependencies
GADTs
InstanceSigs
KindSignatures
LambdaCase
MultiParamTypeClasses
OverloadedLabels
OverloadedStrings
PatternSynonyms
RankNTypes
ScopedTypeVariables
StandaloneDeriving
TupleSections
TypeFamilies
TypeOperators
UndecidableInstances
UnicodeSyntax
ViewPatterns
ConstraintKinds
PackageImports

library
import: library-common
Expand All @@ -78,18 +56,31 @@ library
JRec.Internal
other-modules:
JRec.Tuple
JRec.Field
if flag(with-aeson)
cpp-options: -DWITH_AESON

test-suite jrec-test
import: library-common
type: exitcode-stdio-1.0
hs-source-dirs: test, src
hs-source-dirs: test
main-is: Spec.hs
build-depends:
jrec,
base,
hspec,
QuickCheck,
lens,
should-not-typecheck
lens

test-suite doctests
type: exitcode-stdio-1.0
main-is: doctests.hs
build-depends:
base
, base-compat
, doctest
, QuickCheck
, jrec
, template-haskell
ghc-options: -Wall -threaded
hs-source-dirs: test
default-language: Haskell2010
65 changes: 34 additions & 31 deletions src/JRec.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}

module JRec
( unField,
Expand All @@ -10,7 +21,7 @@ module JRec
append,
union,
insert,
insertOrSet
insertOrSet,
)
where

Expand All @@ -25,12 +36,15 @@ import GHC.Generics
import GHC.OverloadedLabels
import GHC.TypeLits
import Generic.Data
import JRec.Field
import JRec.Internal (Rec, (:=) (..))
import JRec.Internal (Rec, append, (:=) (..))
import qualified JRec.Internal as R
import JRec.Tuple
import Unsafe.Coerce

-- $setup
--
-- >>> :set -XOverloadedLabels

----------------------------------------------------------------------------
-- unField
----------------------------------------------------------------------------
Expand All @@ -42,29 +56,10 @@ unField _ (_ R.:= value) = value
-- Other operations
----------------------------------------------------------------------------

-- Appends records, without removing duplicates.
-- | Merges records, removing duplicates
--
-- O(n + m) type check complexity.
-- Left-biased. Does not sort.
--
-- FIXME: See spec for a bug when there are duplicates.
append ::
forall lhs rhs res.
( KnownNat (R.RecSize lhs),
KnownNat (R.RecSize rhs),
KnownNat (R.RecSize lhs + R.RecSize rhs),
res ~ R.RecAppend lhs rhs,
R.RecCopy lhs lhs res,
R.RecCopy rhs rhs res
) =>
Rec lhs ->
Rec rhs ->
Rec res
append = R.combine

-- Merges records, removing duplicates
--
-- Left-biased. Does not sort.
--
-- O(n * m) type check complexity.
union ::
forall lhs rhs res.
Expand All @@ -80,21 +75,29 @@ union ::
Rec res
union = R.union

-- | Insert a field into a record that does not already contain it
-- | Insert a field into a record.
--
-- O(n) type check complexity.
insert ::
forall label value lts res.
--
-- Will fail at compile time if the record already contains the field:
--
-- >>> (#a := '1') `insert` Rec (#b := '2', #a := '0')
-- ...
-- ... Duplicate key "a"
-- ...
insert ::
forall label value lts res.
( KnownNat (1 + R.RecSize lts),
KnownNat (R.RecSize lts),
KnownSymbol label,
R.RecCopy lts lts res,
res ~ ((label := value) : lts),
R.RemoveAccessTo label lts ~ lts
) =>
R.KeyDoesNotExist label lts
) =>
label := value ->
Rec lts -> Rec res
insert = R.combine . Rec
Rec lts ->
Rec res
insert = R.append . Rec

-- | Insert a field into a record. Set it if it already exists
--
Expand Down
7 changes: 0 additions & 7 deletions src/JRec/Field.hs

This file was deleted.

Loading