packages feed

composite-dhall 0.0.1.0 → 0.0.2.0

raw patch · 5 files changed

+280/−15 lines, 5 filesdep +composite-dhalldep +tastydep +tasty-hunitdep −lensdep ~dhallPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: composite-dhall, tasty, tasty-hunit, vinyl

Dependencies removed: lens

Dependency ranges changed: dhall

API changes (from Hackage documentation)

- Composite.Dhall: instance Dhall.Marshal.Decode.FromDhall (Composite.Record.Record '[])
- Composite.Dhall: instance Dhall.Marshal.Encode.ToDhall (Composite.Record.Record '[])
+ Composite.Dhall: instance (Dhall.Marshal.Decode.FromDhall b, Dhall.Marshal.Encode.ToDhall x) => Dhall.Marshal.Decode.FromDhall (Data.Functor.Contravariant.Op b x)
+ Composite.Dhall: instance (GHC.TypeLits.KnownSymbol s, Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec (Data.Functor.Contravariant.Op b) xs), Dhall.Marshal.Decode.FromDhall b, Dhall.Marshal.Encode.ToDhall x) => Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec (Data.Functor.Contravariant.Op b) ((s Composite.Record.:-> x) : xs))
+ Composite.Dhall: instance (GHC.TypeLits.KnownSymbol s, Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec Data.Functor.Contravariant.Equivalence xs), Dhall.Marshal.Encode.ToDhall x) => Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec Data.Functor.Contravariant.Equivalence ((s Composite.Record.:-> x) : xs))
+ Composite.Dhall: instance (GHC.TypeLits.KnownSymbol s, Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec Data.Functor.Contravariant.Predicate xs), Dhall.Marshal.Encode.ToDhall x) => Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec Data.Functor.Contravariant.Predicate ((s Composite.Record.:-> x) : xs))
+ Composite.Dhall: instance (GHC.TypeLits.KnownSymbol s, Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec GHC.Maybe.Maybe xs), Dhall.Marshal.Decode.FromDhall x) => Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec GHC.Maybe.Maybe ((s Composite.Record.:-> x) : xs))
+ Composite.Dhall: instance (GHC.TypeLits.KnownSymbol s, Dhall.Marshal.Encode.ToDhall (Data.Vinyl.Core.Rec GHC.Maybe.Maybe xs), Dhall.Marshal.Encode.ToDhall x) => Dhall.Marshal.Encode.ToDhall (Data.Vinyl.Core.Rec GHC.Maybe.Maybe ((s Composite.Record.:-> x) : xs))
+ Composite.Dhall: instance Dhall.Marshal.Decode.FromDhall (Data.Vinyl.Core.Rec f '[])
+ Composite.Dhall: instance Dhall.Marshal.Encode.ToDhall (Data.Vinyl.Core.Rec f '[])
+ Composite.Dhall: instance Dhall.Marshal.Encode.ToDhall x => Dhall.Marshal.Decode.FromDhall (Data.Functor.Contravariant.Equivalence x)
+ Composite.Dhall: instance Dhall.Marshal.Encode.ToDhall x => Dhall.Marshal.Decode.FromDhall (Data.Functor.Contravariant.Predicate x)

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # Changelog for composite-dhall +## v0.0.2.0++* Add `ToDhall` and `FromDhall` instances for `Rec Maybe`.+* Add `ToDhall` instances for `Predicate`, `Equivalence` and `Op b`.+* Add `FromDhall` instances for `Rec Predicate`, `Rec Equivalence` and `Rec (Op b)`+ ## v0.0.1.0  * Add `ToDhall` and `FromDhall` instances for composite `Record`s.
README.md view
@@ -2,3 +2,42 @@  `ToDhall` and `FromDhall` instances for [composite](https://hackage.haskell.org/package/composite-base) records.++You can deserialise a normal dhall record such as++```{.dhall}+{ a = "foo"+, b = +5 }+```++using a `Record` like:++```{.haskell}+withLensesAndProxies+  [d|+    type A = "a" :-> Text++    type B = "b" :-> Int+    |]++type MyRec = Record '[A, B]+```++Similarly you can use a contravariant function as the base functor+to parse a collection of templates for different types.++```{.dhall}+{ a = \(x : Text) -> "Hello ${x}."+, b = \(y : Integer) -> "You are ${Integer/show y} years old."+}+```++We use a DerivingVia to avoid overlapping instances in composite:++```+newtype Template a = Template (Op Text a)+  deriving newtype (FromDhall)++newtype Templates = Templates {unTemplates :: Rec Template '[A, B]}+  deriving (FromDhall) via (Rec (Op Text) '[A, B])+```
composite-dhall.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           composite-dhall-version:        0.0.1.0+version:        0.0.2.0 synopsis:       Dhall instances for composite records. description:    Dhall instances for composite records. category:       Dhall@@ -21,7 +21,7 @@  source-repository head   type: git-  location: https://gitlab.com/homotopic-tech/composite-dhall+  location: https://gitlab.homotopic.tech/haskell/composite-dhall  library   exposed-modules:@@ -30,10 +30,30 @@       Paths_composite_dhall   hs-source-dirs:       src+  ghc-options: -Weverything -Wno-all-missed-specialisations -Wno-missing-import-lists -Wno-implicit-prelude -Wno-monomorphism-restriction -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module -Wno-orphans -Wno-safe -Wno-unsafe   build-depends:       base >=4.7 && <5-    , composite-base >=0.7.0.0 && <0.7.7-    , dhall >=1.39.0 && <1.40-    , lens >=5.0.0 && <5.1+    , composite-base >=0.7.0.0 && <0.8+    , dhall >=1.34.0 && <1.40     , text >=1.0 && <1.4+    , vinyl+  default-language: Haskell2010++test-suite composite-dhall-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_composite_dhall+  hs-source-dirs:+      test+  ghc-options: -Weverything -Wno-all-missed-specialisations -Wno-missing-import-lists -Wno-implicit-prelude -Wno-monomorphism-restriction -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module -Wno-orphans -Wno-safe -Wno-unsafe -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , composite-base >=0.7.0.0 && <0.8+    , composite-dhall+    , dhall >=1.34.0 && <1.40+    , tasty+    , tasty-hunit+    , text >=1.0 && <1.4+    , vinyl   default-language: Haskell2010
src/Composite/Dhall.hs view
@@ -1,26 +1,27 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralisedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}  module Composite.Dhall () where  import Composite.Record-import Composite.TH import Control.Applicative-import qualified Control.Lens as L import Data.Functor.Contravariant import Data.Text (Text)-import qualified Data.Text as T import Data.Void import qualified Dhall as D-import Dhall.Core hiding (File, Text, field)+import Dhall.Core hiding (File, Text) import Dhall.Map import Dhall.Src import GHC.TypeLits@@ -41,7 +42,7 @@   Dhall.Core.internalError     (name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression) -instance D.ToDhall (Record '[]) where+instance D.ToDhall (Rec f '[]) where   injectWith = pure (D.Encoder {..})     where       embed _ = RecordLit mempty@@ -54,15 +55,30 @@     let name = valName f     let D.Encoder embedL declaredL = D.inject     let D.Encoder embedR declaredR = D.inject-    let embed (s :*: xs) = RecordLit (Dhall.Map.insert name (Dhall.Core.makeRecordField (embedL $ s)) mapR)+    let embed (s :*: xs) = RecordLit (Dhall.Map.insert name (Dhall.Core.makeRecordField (embedL s)) mapR)           where             mapR = unsafeExpectRecordLit "Composite Record" $ embedR xs-    let declared = Record (Dhall.Map.insert name (Dhall.Core.makeRecordField (declaredL)) mapR)+    let declared = Record (Dhall.Map.insert name (Dhall.Core.makeRecordField declaredL) mapR)           where             mapR = unsafeExpectRecord "Composite Record" declaredR     pure $ D.Encoder {..} -instance D.FromDhall (Record '[]) where+instance (KnownSymbol s, D.ToDhall (Rec Maybe xs), D.ToDhall x) => D.ToDhall (Rec Maybe (s :-> x ': xs)) where+  injectWith = do+    let f :: s :-> x+        f = undefined+    let name = valName f+    let D.Encoder embedL declaredL = D.inject+    let D.Encoder embedR declaredR = D.inject+    let embed (s :^: xs) = RecordLit (Dhall.Map.insert name (Dhall.Core.makeRecordField (embedL s)) mapR)+          where+            mapR = unsafeExpectRecordLit "Composite Record" $ embedR xs+    let declared = Record (Dhall.Map.insert name (Dhall.Core.makeRecordField declaredL) mapR)+          where+            mapR = unsafeExpectRecord "Composite Record" declaredR+    pure $ D.Encoder {..}++instance D.FromDhall (Rec f '[]) where   autoWith _ = D.Decoder {..}     where       extract _ = pure RNil@@ -92,6 +108,128 @@                   liftA2                     (:*:)                     (extractL expressionL)+                    (extractR expression)+                _ -> die+            _ -> die+    pure (D.Decoder extract expected)++instance (KnownSymbol s, D.FromDhall (Rec Maybe xs), D.FromDhall x) => D.FromDhall (Rec Maybe (s :-> x ': xs)) where+  autoWith = do+    let nL :: s :-> x+        nL = undefined++    let nameL = valName nL++    D.Decoder extractL expectedL <- D.autoWith @(Maybe x)++    D.Decoder extractR expectedR <- D.autoWith @(Rec Maybe xs)++    let ktsR = unsafeExpectRecord "Composite Record" <$> expectedR++    let expected = Record <$> (Dhall.Map.insert nameL . Dhall.Core.makeRecordField <$> expectedL <*> ktsR)+    let extract expression = do+          let die = D.typeError expected expression++          case expression of+            RecordLit kvs ->+              case Dhall.Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                Just expressionL ->+                  liftA2+                    (:^:)+                    (extractL expressionL)+                    (extractR expression)+                _ -> die+            _ -> die+    pure (D.Decoder extract expected)++deriving newtype instance (D.FromDhall b, D.ToDhall x) => D.FromDhall (Op b x)++deriving newtype instance (D.ToDhall x) => D.FromDhall (Predicate x)++deriving newtype instance (D.ToDhall x) => D.FromDhall (Equivalence x)++instance (KnownSymbol s, D.FromDhall (Rec (Op b) xs), D.FromDhall b, D.ToDhall x) => D.FromDhall (Rec (Op b) (s :-> x ': xs)) where+  autoWith = do+    let nL :: s :-> x+        nL = undefined++    let nameL = valName nL++    D.Decoder extractL expectedL <- D.autoWith @(Op b x)++    D.Decoder extractR expectedR <- D.autoWith @(Rec (Op b) xs)++    let ktsR = unsafeExpectRecord "Composite Record" <$> expectedR++    let expected = Record <$> (Dhall.Map.insert nameL . Dhall.Core.makeRecordField <$> expectedL <*> ktsR)+    let extract expression = do+          let die = D.typeError expected expression++          case expression of+            RecordLit kvs ->+              case Dhall.Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                Just expressionL ->+                  liftA2+                    (:&)+                    (contramap getVal <$> extractL expressionL)+                    (extractR expression)+                _ -> die+            _ -> die+    pure (D.Decoder extract expected)++instance (KnownSymbol s, D.FromDhall (Rec Predicate xs), D.ToDhall x) => D.FromDhall (Rec Predicate (s :-> x ': xs)) where+  autoWith = do+    let nL :: s :-> x+        nL = undefined++    let nameL = valName nL++    D.Decoder extractL expectedL <- D.autoWith @(Predicate x)++    D.Decoder extractR expectedR <- D.autoWith @(Rec Predicate xs)++    let ktsR = unsafeExpectRecord "Composite Record" <$> expectedR++    let expected = Record <$> (Dhall.Map.insert nameL . Dhall.Core.makeRecordField <$> expectedL <*> ktsR)+    let extract expression = do+          let die = D.typeError expected expression++          case expression of+            RecordLit kvs ->+              case Dhall.Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                Just expressionL ->+                  liftA2+                    (:&)+                    (contramap getVal <$> extractL expressionL)+                    (extractR expression)+                _ -> die+            _ -> die+    pure (D.Decoder extract expected)++instance (KnownSymbol s, D.FromDhall (Rec Equivalence xs), D.ToDhall x) => D.FromDhall (Rec Equivalence (s :-> x ': xs)) where+  autoWith = do+    let nL :: s :-> x+        nL = undefined++    let nameL = valName nL++    D.Decoder extractL expectedL <- D.autoWith @(Equivalence x)++    D.Decoder extractR expectedR <- D.autoWith @(Rec Equivalence xs)++    let ktsR = unsafeExpectRecord "Composite Record" <$> expectedR++    let expected = Record <$> (Dhall.Map.insert nameL . Dhall.Core.makeRecordField <$> expectedL <*> ktsR)+    let extract expression = do+          let die = D.typeError expected expression++          case expression of+            RecordLit kvs ->+              case Dhall.Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+                Just expressionL ->+                  liftA2+                    (:&)+                    (contramap getVal <$> extractL expressionL)                     (extractR expression)                 _ -> die             _ -> die
+ test/Spec.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralisedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}++module Main (main) where++import Composite+import Composite.Dhall ()+import Composite.TH+import Data.Functor.Contravariant+import Data.Text+import Dhall+import Test.Tasty+import Test.Tasty.HUnit++withLensesAndProxies+  [d|+    type A = "a" :-> Text++    type B = "b" :-> Int+    |]++type RecId = Record '[A, B]++type RecMaybe = Rec Maybe '[A, B]++newtype Template a = Template (Op Text a)+  deriving newtype (FromDhall)++recId :: RecId+recId = "foo" :*: 5 :*: RNil++recMaybe :: RecMaybe+recMaybe = Just "foo" :^: Just 5 :^: RNil++newtype Templates = Templates {unTemplates :: Rec Template '[A, B]}+  deriving (FromDhall) via (Rec (Op Text) '[A, B])++tests :: TestTree+tests =+  testGroup+    "Parsing Tests"+    [ testCase "parses Record" $ do+        x <- input auto "./test/data/A.dhall"+        assertEqual "" recId x,+      testCase "parses Maybe Rec" $ do+        x <- input auto "./test/data/B.dhall"+        assertEqual "" recMaybe x,+      testCase "parses Contravariant" $ do+        (_ :: Templates) <- input auto "./test/data/C.dhall"+        pure ()+    ]++main :: IO ()+main = defaultMain tests