packages feed

bookkeeper 0.2.2.0 → 0.2.3

raw patch · 5 files changed

+72/−6 lines, 5 files

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.2.3++* Implement 'fromRecord' for converting values from record.+ # 0.2.2.0  * Add 'Data.Default' instance
README.md view
@@ -39,8 +39,8 @@ is, in:  ~~~ {.haskell}--- type A = Book '[ "field1" :=> Int, "field2" :=> Bool]--- type B = Book '[ "field2" :=> Bool "field1" :=> Int ]+-- type A = Book '[ "field1" :=> Int,  "field2" :=> Bool]+-- type B = Book '[ "field2" :=> Bool, "field1" :=> Int ] ~~~  Types `A` and `B` are the same.
bookkeeper.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           bookkeeper-version:        0.2.2.0+version:        0.2.3 synopsis:       Anonymous records and overloaded labels description:    Please see README.md category:       Data Structures, Records
src/Bookkeeper.hs view
@@ -37,6 +37,10 @@   , Book   , (:=>)   , Key++  -- * From Haskell record+  , fromRecord+   -- * Re-exports   , (&) 
src/Bookkeeper/Internal.hs view
@@ -3,9 +3,9 @@ module Bookkeeper.Internal where  import GHC.OverloadedLabels-import GHC.Generics (Generic)+import GHC.Generics import qualified Data.Type.Map as Map-import GHC.TypeLits (Symbol, KnownSymbol)+import GHC.TypeLits (Symbol, KnownSymbol, TypeError, ErrorMessage(..)) import Data.Default.Class (Default(..)) import Data.Kind (Type) import Data.Type.Map (Map, Mapping((:->)))@@ -126,7 +126,7 @@ -- resulting book will have type 'Book new'. type Settable field val old new =   (-     Map.Submap (Map.AsMap (old Map.:\ field)) old+    Map.Submap (Map.AsMap (old Map.:\ field)) old   , Map.Unionable '[ field :=> val] (Map.AsMap (old Map.:\ field))   , new ~ Map.AsMap (( field :=> val) ': (Map.AsMap (old Map.:\ field)))   )@@ -207,6 +207,64 @@         ) => Key field -> Book' old -> Book (old Map.:\ field) delete _ (Book bk) = Book $ Map.submap bk ++-- * Generics++class FromGeneric a book | a -> book where+  fromGeneric :: a x -> Book' book++instance FromGeneric cs book => FromGeneric (D1 m cs) book where+  fromGeneric (M1 xs) = fromGeneric xs++instance FromGeneric cs book => FromGeneric (C1 m cs) book where+  fromGeneric (M1 xs) = fromGeneric xs++instance (v ~ Map.AsMap ('[name ':-> t]))+  => FromGeneric (S1 ('MetaSel ('Just name) p s l) (Rec0 t)) v where+  fromGeneric (M1 (K1 t)) = (Key =: t) emptyBook++instance+  ( FromGeneric l lbook+  , FromGeneric r rbook+  , Map.Unionable lbook rbook+  , book ~ Map.Union lbook rbook+  ) => FromGeneric (l :*: r) book where+  fromGeneric (l :*: r)+    = Book $ Map.union (getBook (fromGeneric l)) (getBook (fromGeneric r))++type family Expected a where+  Expected (l :+: r) = TypeError ('Text "Cannot convert sum types into Books")+  Expected U1        = TypeError ('Text "Cannot convert non-record types into Books")++instance (book ~ Expected (l :+: r)) => FromGeneric (l :+: r) book where+  fromGeneric = error "impossible"++instance (book ~ Expected U1) => FromGeneric U1 book where+  fromGeneric = error "impossible"+++-- | Generate a @Book@ from an ordinary Haskell record via GHC Generics.+--+-- >>> data Test = Test {  field1 :: String, field2 :: Int, field3 :: Char } deriving Generic+-- >>> fromRecord (Test "hello" 0 'c')+-- Book {field1 = "hello", field2 = 0, field3 = 'c'}+--+-- Trying to convert a datatype which is not a record will result in a type+-- error:+--+-- >>> data SomeSumType = LeftSide | RightSide deriving Generic+-- >>> fromRecord LeftSide+-- ...+-- ... • Cannot convert sum types into Books+-- ...+--+-- >>> data Unit = Unit deriving Generic+-- >>> fromRecord Unit+-- ...+-- ... • Cannot convert non-record types into Books+-- ...+fromRecord :: (Generic a, FromGeneric (Rep a) bookRep) => a -> Book' bookRep+fromRecord = fromGeneric . from  -- $setup -- >>> import Data.Function ((&))