dhall 1.38.1 → 1.39.0
raw patch · 96 files changed
+3828/−3237 lines, 96 filesdep ~cryptonitedep ~generic-randomdep ~megaparsecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: cryptonite, generic-random, megaparsec, mmorph, template-haskell
API changes (from Hackage documentation)
- Dhall: (>$<) :: Contravariant f => (a -> b) -> f b -> f a
- Dhall: (>*<) :: Divisible f => f a -> f b -> f (a, b)
- Dhall: (>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)
- Dhall: Bare :: SingletonConstructors
- Dhall: Decoder :: (Expr Src Void -> Extractor Src Void a) -> Expector (Expr Src Void) -> Decoder a
- Dhall: DhallErrors :: NonEmpty e -> DhallErrors e
- Dhall: Encoder :: (a -> Expr Src Void) -> Expr Src Void -> Encoder a
- Dhall: ExpectedTypeError :: ExpectedTypeError -> ExtractError s a
- Dhall: ExtractError :: Text -> ExtractError s a
- Dhall: InputNormalizer :: ReifiedNormalizer Void -> InputNormalizer
- Dhall: InterpretOptions :: (Text -> Text) -> (Text -> Text) -> SingletonConstructors -> InterpretOptions
- Dhall: InvalidDecoder :: Expr s a -> Expr s a -> InvalidDecoder s a
- Dhall: RecordDecoder :: Product (Const (Map Text (Expector (Expr Src Void)))) (Compose ((->) (Expr Src Void)) (Extractor Src Void)) a -> RecordDecoder a
- Dhall: RecordEncoder :: Map Text (Encoder a) -> RecordEncoder a
- Dhall: RecursiveTypeError :: ExpectedTypeError
- Dhall: Smart :: SingletonConstructors
- Dhall: TypeMismatch :: InvalidDecoder s a -> ExtractError s a
- Dhall: UnionDecoder :: Compose (Map Text) Decoder a -> UnionDecoder a
- Dhall: UnionEncoder :: Product (Const (Map Text (Expr Src Void))) (Op (Text, Expr Src Void)) a -> UnionEncoder a
- Dhall: Wrapped :: SingletonConstructors
- Dhall: [constructorModifier] :: InterpretOptions -> Text -> Text
- Dhall: [declared] :: Encoder a -> Expr Src Void
- Dhall: [embed] :: Encoder a -> a -> Expr Src Void
- Dhall: [expected] :: Decoder a -> Expector (Expr Src Void)
- Dhall: [extract] :: Decoder a -> Expr Src Void -> Extractor Src Void a
- Dhall: [fieldModifier] :: InterpretOptions -> Text -> Text
- Dhall: [getErrors] :: DhallErrors e -> NonEmpty e
- Dhall: [getInputNormalizer] :: InputNormalizer -> ReifiedNormalizer Void
- Dhall: [invalidDecoderExpected] :: InvalidDecoder s a -> Expr s a
- Dhall: [invalidDecoderExpression] :: InvalidDecoder s a -> Expr s a
- Dhall: [singletonConstructors] :: InterpretOptions -> SingletonConstructors
- Dhall: auto :: FromDhall a => Decoder a
- Dhall: autoWith :: (FromDhall a, Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a
- Dhall: bool :: Decoder Bool
- Dhall: class FromDhall a
- Dhall: class Generic a
- Dhall: class GenericFromDhall t f
- Dhall: class GenericFromDhallUnion t f
- Dhall: class GenericToDhall f
- Dhall: class ToDhall a
- Dhall: constructor :: Text -> Decoder a -> UnionDecoder a
- Dhall: data Decoder a
- Dhall: data Encoder a
- Dhall: data ExpectedTypeError
- Dhall: data ExtractError s a
- Dhall: data InterpretOptions
- Dhall: data InvalidDecoder s a
- Dhall: data Natural
- Dhall: data Result f
- Dhall: data Seq a
- Dhall: data SingletonConstructors
- Dhall: data Text
- Dhall: data Vector a
- Dhall: defaultInputNormalizer :: InputNormalizer
- Dhall: defaultInterpretOptions :: InterpretOptions
- Dhall: double :: Decoder Double
- Dhall: encodeConstructor :: ToDhall a => Text -> UnionEncoder a
- Dhall: encodeConstructorWith :: Text -> Encoder a -> UnionEncoder a
- Dhall: encodeField :: ToDhall a => Text -> RecordEncoder a
- Dhall: encodeFieldWith :: Text -> Encoder a -> RecordEncoder a
- Dhall: extractError :: Text -> Extractor s a b
- Dhall: field :: Text -> Decoder a -> RecordDecoder a
- Dhall: fromMonadic :: MonadicExtractor s a b -> Extractor s a b
- Dhall: function :: Encoder a -> Decoder b -> Decoder (a -> b)
- Dhall: functionWith :: InputNormalizer -> Encoder a -> Decoder b -> Decoder (a -> b)
- Dhall: genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a
- Dhall: genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a
- Dhall: genericAutoWithNormalizer :: GenericFromDhall t f => Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))
- Dhall: genericToDhall :: (Generic a, GenericToDhall (Rep a)) => Encoder a
- Dhall: genericToDhallWith :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a
- Dhall: genericToDhallWithNormalizer :: GenericToDhall f => InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))
- Dhall: genericUnionAutoWithNormalizer :: GenericFromDhallUnion t f => Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)
- Dhall: hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)
- Dhall: hashSetFromDistinctList :: (Hashable a, Ord a, Show a) => Decoder a -> Decoder (HashSet a)
- Dhall: hashSetIgnoringDuplicates :: (Hashable a, Ord a) => Decoder a -> Decoder (HashSet a)
- Dhall: infixl 4 >$<
- Dhall: infixr 5 >*<
- Dhall: inject :: ToDhall a => Encoder a
- Dhall: injectWith :: (ToDhall a, Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a
- Dhall: instance (Dhall.FromDhall a, Data.Hashable.Class.Hashable a, GHC.Classes.Ord a, GHC.Show.Show a) => Dhall.FromDhall (Data.HashSet.Internal.HashSet a)
- Dhall: instance (Dhall.FromDhall a, Dhall.FromDhall b) => Dhall.FromDhall (a, b)
- Dhall: instance (Dhall.FromDhall a, GHC.Classes.Ord a, GHC.Show.Show a) => Dhall.FromDhall (Data.Set.Internal.Set a)
- Dhall: instance (Dhall.ToDhall a, Dhall.FromDhall b) => Dhall.FromDhall (a -> b)
- Dhall: instance (Dhall.ToDhall a, Dhall.ToDhall b) => Dhall.ToDhall (a, b)
- Dhall: instance (Dhall.ToDhall k, Dhall.ToDhall v) => Dhall.ToDhall (Data.HashMap.Internal.HashMap k v)
- Dhall: instance (Dhall.ToDhall k, Dhall.ToDhall v) => Dhall.ToDhall (Data.Map.Internal.Map k v)
- Dhall: instance (GHC.Base.Functor f, Dhall.FromDhall (f (Dhall.Result f))) => Dhall.FromDhall (Data.Fix.Fix f)
- Dhall: instance (GHC.Base.Functor f, Dhall.ToDhall (f (Dhall.Result f))) => Dhall.ToDhall (Data.Fix.Fix f)
- Dhall: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k, Dhall.FromDhall k, Dhall.FromDhall v) => Dhall.FromDhall (Data.HashMap.Internal.HashMap k v)
- Dhall: instance (GHC.Classes.Ord k, Dhall.FromDhall k, Dhall.FromDhall v) => Dhall.FromDhall (Data.Map.Internal.Map k v)
- Dhall: instance (GHC.Generics.Selector s, Dhall.ToDhall a) => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
- Dhall: instance (GHC.Generics.Selector s1, GHC.Generics.Selector s2, Dhall.ToDhall a1, Dhall.ToDhall a2) => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
- Dhall: instance (GHC.Show.Show (Dhall.DhallErrors e), Data.Typeable.Internal.Typeable e) => GHC.Exception.Type.Exception (Dhall.DhallErrors e)
- Dhall: instance (Prettyprinter.Internal.Pretty s, Data.Typeable.Internal.Typeable s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable a) => GHC.Exception.Type.Exception (Dhall.InvalidDecoder s a)
- Dhall: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Exception.Type.Exception (Dhall.ExtractError s a)
- Dhall: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.ExtractError s a)
- Dhall: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.ExtractErrors s a)
- Dhall: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.InvalidDecoder s a)
- Dhall: instance Data.Functor.Contravariant.Contravariant Dhall.Encoder
- Dhall: instance Data.Functor.Contravariant.Contravariant Dhall.RecordEncoder
- Dhall: instance Data.Functor.Contravariant.Contravariant Dhall.UnionEncoder
- Dhall: instance Data.Functor.Contravariant.Divisible.Divisible Dhall.RecordEncoder
- Dhall: instance Dhall.FromDhall ()
- Dhall: instance Dhall.FromDhall (f (Dhall.Result f)) => Dhall.FromDhall (Dhall.Result f)
- Dhall: instance Dhall.FromDhall Data.Scientific.Scientific
- Dhall: instance Dhall.FromDhall Data.Text.Internal.Lazy.Text
- Dhall: instance Dhall.FromDhall Data.Text.Internal.Text
- Dhall: instance Dhall.FromDhall Data.Void.Void
- Dhall: instance Dhall.FromDhall GHC.Int.Int16
- Dhall: instance Dhall.FromDhall GHC.Int.Int32
- Dhall: instance Dhall.FromDhall GHC.Int.Int64
- Dhall: instance Dhall.FromDhall GHC.Int.Int8
- Dhall: instance Dhall.FromDhall GHC.Integer.Type.Integer
- Dhall: instance Dhall.FromDhall GHC.Natural.Natural
- Dhall: instance Dhall.FromDhall GHC.Types.Bool
- Dhall: instance Dhall.FromDhall GHC.Types.Double
- Dhall: instance Dhall.FromDhall GHC.Types.Int
- Dhall: instance Dhall.FromDhall GHC.Types.Word
- Dhall: instance Dhall.FromDhall GHC.Word.Word16
- Dhall: instance Dhall.FromDhall GHC.Word.Word32
- Dhall: instance Dhall.FromDhall GHC.Word.Word64
- Dhall: instance Dhall.FromDhall GHC.Word.Word8
- Dhall: instance Dhall.FromDhall [GHC.Types.Char]
- Dhall: instance Dhall.FromDhall a => Dhall.FromDhall (Data.Sequence.Internal.Seq a)
- Dhall: instance Dhall.FromDhall a => Dhall.FromDhall (Data.Vector.Vector a)
- Dhall: instance Dhall.FromDhall a => Dhall.FromDhall (GHC.Maybe.Maybe a)
- Dhall: instance Dhall.FromDhall a => Dhall.FromDhall [a]
- Dhall: instance Dhall.GenericFromDhall a (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
- Dhall: instance Dhall.GenericFromDhall a1 (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
- Dhall: instance Dhall.GenericFromDhall a2 (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
- Dhall: instance Dhall.GenericToDhall GHC.Generics.U1
- Dhall: instance Dhall.ToDhall ()
- Dhall: instance Dhall.ToDhall (f (Dhall.Result f)) => Dhall.ToDhall (Dhall.Result f)
- Dhall: instance Dhall.ToDhall Data.Scientific.Scientific
- Dhall: instance Dhall.ToDhall Data.Text.Internal.Lazy.Text
- Dhall: instance Dhall.ToDhall Data.Text.Internal.Text
- Dhall: instance Dhall.ToDhall Data.Void.Void
- Dhall: instance Dhall.ToDhall GHC.Base.String
- Dhall: instance Dhall.ToDhall GHC.Integer.Type.Integer
- Dhall: instance Dhall.ToDhall GHC.Natural.Natural
- Dhall: instance Dhall.ToDhall GHC.Types.Bool
- Dhall: instance Dhall.ToDhall GHC.Types.Double
- Dhall: instance Dhall.ToDhall GHC.Types.Int
- Dhall: instance Dhall.ToDhall GHC.Types.Word
- Dhall: instance Dhall.ToDhall GHC.Word.Word16
- Dhall: instance Dhall.ToDhall GHC.Word.Word32
- Dhall: instance Dhall.ToDhall GHC.Word.Word64
- Dhall: instance Dhall.ToDhall GHC.Word.Word8
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall (Data.HashSet.Internal.HashSet a)
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall (Data.Sequence.Internal.Seq a)
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall (Data.Set.Internal.Set a)
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall (Data.Vector.Vector a)
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall (GHC.Maybe.Maybe a)
- Dhall: instance Dhall.ToDhall a => Dhall.ToDhall [a]
- Dhall: instance GHC.Base.Applicative Dhall.RecordDecoder
- Dhall: instance GHC.Base.Functor Dhall.Decoder
- Dhall: instance GHC.Base.Functor Dhall.DhallErrors
- Dhall: instance GHC.Base.Functor Dhall.RecordDecoder
- Dhall: instance GHC.Base.Functor Dhall.UnionDecoder
- Dhall: instance GHC.Base.Monoid (Dhall.UnionDecoder a)
- Dhall: instance GHC.Base.Semigroup (Dhall.DhallErrors e)
- Dhall: instance GHC.Base.Semigroup (Dhall.UnionDecoder a)
- Dhall: instance GHC.Classes.Eq Dhall.ExpectedTypeError
- Dhall: instance GHC.Classes.Eq e => GHC.Classes.Eq (Dhall.DhallErrors e)
- Dhall: instance GHC.Exception.Type.Exception Dhall.ExpectedTypeError
- Dhall: instance GHC.Show.Show Dhall.ExpectedTypeError
- Dhall: instance GHC.Show.Show Dhall.ExpectedTypeErrors
- Dhall: instance forall k (c :: GHC.Generics.Meta) (f :: k -> *) (g :: k -> *) (h :: k -> *). (GHC.Generics.Constructor c, Dhall.GenericToDhall (f GHC.Generics.:+: g), Dhall.GenericToDhall h) => Dhall.GenericToDhall ((f GHC.Generics.:+: g) GHC.Generics.:+: GHC.Generics.M1 GHC.Generics.C c h)
- Dhall: instance forall k (c :: GHC.Generics.Meta) (f :: k -> *) (g :: k -> *) (h :: k -> *). (GHC.Generics.Constructor c, Dhall.GenericToDhall f, Dhall.GenericToDhall (g GHC.Generics.:+: h)) => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c f GHC.Generics.:+: (g GHC.Generics.:+: h))
- Dhall: instance forall k (c1 :: GHC.Generics.Meta) (c2 :: GHC.Generics.Meta) (f1 :: k -> *) (f2 :: k -> *). (GHC.Generics.Constructor c1, GHC.Generics.Constructor c2, Dhall.GenericToDhall f1, Dhall.GenericToDhall f2) => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c1 f1 GHC.Generics.:+: GHC.Generics.M1 GHC.Generics.C c2 f2)
- Dhall: instance forall k (f :: k -> *) (c :: GHC.Generics.Meta). Dhall.GenericToDhall f => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c f)
- Dhall: instance forall k (f :: k -> *) (d :: GHC.Generics.Meta). Dhall.GenericToDhall f => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.D d f)
- Dhall: instance forall k (f :: k -> *) (g :: k -> *) (h :: k -> *) (i :: k -> *). (Dhall.GenericToDhall (f GHC.Generics.:*: g), Dhall.GenericToDhall (h GHC.Generics.:*: i)) => Dhall.GenericToDhall ((f GHC.Generics.:*: g) GHC.Generics.:*: (h GHC.Generics.:*: i))
- Dhall: instance forall k (f :: k -> *) (g :: k -> *) (h :: k -> *) (i :: k -> *). (Dhall.GenericToDhall (f GHC.Generics.:+: g), Dhall.GenericToDhall (h GHC.Generics.:+: i)) => Dhall.GenericToDhall ((f GHC.Generics.:+: g) GHC.Generics.:+: (h GHC.Generics.:+: i))
- Dhall: instance forall k (f :: k -> *) (g :: k -> *) (s :: GHC.Generics.Meta) a i. (Dhall.GenericToDhall (f GHC.Generics.:*: g), GHC.Generics.Selector s, Dhall.ToDhall a) => Dhall.GenericToDhall ((f GHC.Generics.:*: g) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
- Dhall: instance forall k (s :: GHC.Generics.Meta) a (f :: k -> *) (g :: k -> *) i. (GHC.Generics.Selector s, Dhall.ToDhall a, Dhall.GenericToDhall (f GHC.Generics.:*: g)) => Dhall.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a) GHC.Generics.:*: (f GHC.Generics.:*: g))
- Dhall: instance forall k1 k2 (c1 :: GHC.Generics.Meta) (t :: k1) (f1 :: k2 -> *). (GHC.Generics.Constructor c1, Dhall.GenericFromDhall t f1) => Dhall.GenericFromDhallUnion t (GHC.Generics.M1 GHC.Generics.C c1 f1)
- Dhall: instance forall k1 k2 (s :: GHC.Generics.Meta) a (t :: k1) (f :: k2 -> *) (g :: k2 -> *) i. (GHC.Generics.Selector s, Dhall.FromDhall a, Dhall.GenericFromDhall t (f GHC.Generics.:*: g)) => Dhall.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a) GHC.Generics.:*: (f GHC.Generics.:*: g))
- Dhall: instance forall k1 k2 (s :: GHC.Generics.Meta) a (t :: k1) i. (GHC.Generics.Selector s, Dhall.FromDhall a) => Dhall.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
- Dhall: instance forall k1 k2 (s1 :: GHC.Generics.Meta) (s2 :: GHC.Generics.Meta) a1 a2 (t :: k1) i1 i2. (GHC.Generics.Selector s1, GHC.Generics.Selector s2, Dhall.FromDhall a1, Dhall.FromDhall a2) => Dhall.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
- Dhall: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (c :: GHC.Generics.Meta). Dhall.GenericFromDhall t f => Dhall.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.C c f)
- Dhall: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (d :: GHC.Generics.Meta). Dhall.GenericFromDhall t f => Dhall.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.D d f)
- Dhall: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *) (h :: k2 -> *) (i :: k2 -> *). (Dhall.GenericFromDhall t (f GHC.Generics.:*: g), Dhall.GenericFromDhall t (h GHC.Generics.:*: i)) => Dhall.GenericFromDhall t ((f GHC.Generics.:*: g) GHC.Generics.:*: (h GHC.Generics.:*: i))
- Dhall: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *) (s :: GHC.Generics.Meta) a i. (Dhall.GenericFromDhall t (f GHC.Generics.:*: g), GHC.Generics.Selector s, Dhall.FromDhall a) => Dhall.GenericFromDhall t ((f GHC.Generics.:*: g) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
- Dhall: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *). Dhall.GenericFromDhallUnion t (f GHC.Generics.:+: g) => Dhall.GenericFromDhall t (f GHC.Generics.:+: g)
- Dhall: instance forall k1 k2 (t :: k1) (f1 :: k2 -> *) (f2 :: k2 -> *). (Dhall.GenericFromDhallUnion t f1, Dhall.GenericFromDhallUnion t f2) => Dhall.GenericFromDhallUnion t (f1 GHC.Generics.:+: f2)
- Dhall: instance forall k1 k2 (t :: k1). Dhall.GenericFromDhall t GHC.Generics.U1
- Dhall: instance forall k1 k2 (t :: k1). Dhall.GenericFromDhall t GHC.Generics.V1
- Dhall: int :: Decoder Int
- Dhall: int16 :: Decoder Int16
- Dhall: int32 :: Decoder Int32
- Dhall: int64 :: Decoder Int64
- Dhall: int8 :: Decoder Int8
- Dhall: integer :: Decoder Integer
- Dhall: lazyText :: Decoder Text
- Dhall: list :: Decoder a -> Decoder [a]
- Dhall: map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)
- Dhall: maybe :: Decoder a -> Decoder (Maybe a)
- Dhall: natural :: Decoder Natural
- Dhall: newtype DhallErrors e
- Dhall: newtype InputNormalizer
- Dhall: newtype RecordDecoder a
- Dhall: newtype RecordEncoder a
- Dhall: newtype UnionDecoder a
- Dhall: newtype UnionEncoder a
- Dhall: pair :: Decoder a -> Decoder b -> Decoder (a, b)
- Dhall: pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)
- Dhall: record :: RecordDecoder a -> Decoder a
- Dhall: recordEncoder :: RecordEncoder a -> Encoder a
- Dhall: scientific :: Decoder Scientific
- Dhall: sequence :: Decoder a -> Decoder (Seq a)
- Dhall: setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Set a)
- Dhall: setIgnoringDuplicates :: Ord a => Decoder a -> Decoder (Set a)
- Dhall: showDhallErrors :: Show e => String -> DhallErrors e -> String
- Dhall: strictText :: Decoder Text
- Dhall: string :: Decoder String
- Dhall: toMonadic :: Extractor s a b -> MonadicExtractor s a b
- Dhall: type ExpectedTypeErrors = DhallErrors ExpectedTypeError
- Dhall: type Expector = Validation ExpectedTypeErrors
- Dhall: type ExtractErrors s a = DhallErrors (ExtractError s a)
- Dhall: type Extractor s a = Validation (ExtractErrors s a)
- Dhall: type Inject = ToDhall
- Dhall: type Interpret = FromDhall
- Dhall: type MonadicExtractor s a = Either (ExtractErrors s a)
- Dhall: typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b
- Dhall: union :: UnionDecoder a -> Decoder a
- Dhall: unionEncoder :: UnionEncoder a -> Encoder a
- Dhall: unit :: Decoder ()
- Dhall: vector :: Decoder a -> Decoder (Vector a)
- Dhall: void :: Decoder Void
- Dhall: word :: Decoder Word
- Dhall: word16 :: Decoder Word16
- Dhall: word32 :: Decoder Word32
- Dhall: word64 :: Decoder Word64
- Dhall: word8 :: Decoder Word8
- Dhall.Binary: NoVersion :: StandardVersion
- Dhall.Binary: V_1_0_0 :: StandardVersion
- Dhall.Binary: V_2_0_0 :: StandardVersion
- Dhall.Binary: V_3_0_0 :: StandardVersion
- Dhall.Binary: V_4_0_0 :: StandardVersion
- Dhall.Binary: V_5_0_0 :: StandardVersion
- Dhall.Binary: data StandardVersion
- Dhall.Binary: instance GHC.Enum.Bounded Dhall.Binary.StandardVersion
- Dhall.Binary: instance GHC.Enum.Enum Dhall.Binary.StandardVersion
- Dhall.Binary: renderStandardVersion :: StandardVersion -> Text
- Dhall.Deriving: instance forall k a (tag :: k). (GHC.Generics.Generic a, Dhall.GenericFromDhall a (GHC.Generics.Rep a), Dhall.Deriving.ModifyOptions tag) => Dhall.FromDhall (Dhall.Deriving.Codec tag a)
- Dhall.Deriving: instance forall k a (tag :: k). (GHC.Generics.Generic a, Dhall.GenericToDhall (GHC.Generics.Rep a), Dhall.Deriving.ModifyOptions tag) => Dhall.ToDhall (Dhall.Deriving.Codec tag a)
- Dhall.Format: [input] :: Format -> PossiblyTransitiveInput
- Dhall.Main: [possiblyTransitiveInput] :: Mode -> PossiblyTransitiveInput
- Dhall.Util: NonTransitiveStandardInput :: PossiblyTransitiveInput
- Dhall.Util: PossiblyTransitiveInputFile :: FilePath -> Transitivity -> PossiblyTransitiveInput
- Dhall.Util: data CheckFailed
- Dhall.Util: data PossiblyTransitiveInput
- Dhall.Util: instance GHC.Exception.Type.Exception Dhall.Util.CheckFailed
- Dhall.Util: instance GHC.Show.Show Dhall.Util.CheckFailed
+ Dhall.Deriving: instance forall k a (tag :: k). (GHC.Generics.Generic a, Dhall.Marshal.Decode.GenericFromDhall a (GHC.Generics.Rep a), Dhall.Deriving.ModifyOptions tag) => Dhall.Marshal.Decode.FromDhall (Dhall.Deriving.Codec tag a)
+ Dhall.Deriving: instance forall k a (tag :: k). (GHC.Generics.Generic a, Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.Rep a), Dhall.Deriving.ModifyOptions tag) => Dhall.Marshal.Encode.ToDhall (Dhall.Deriving.Codec tag a)
+ Dhall.Format: [inputs] :: Format -> NonEmpty Input
+ Dhall.Format: [transitivity] :: Format -> Transitivity
+ Dhall.Main: [deprecatedInPlace] :: Mode -> Bool
+ Dhall.Main: [inputs] :: Mode -> NonEmpty Input
+ Dhall.Main: [transitivity] :: Mode -> Transitivity
+ Dhall.Marshal.Decode: Bare :: SingletonConstructors
+ Dhall.Marshal.Decode: Decoder :: (Expr Src Void -> Extractor Src Void a) -> Expector (Expr Src Void) -> Decoder a
+ Dhall.Marshal.Decode: DhallErrors :: NonEmpty e -> DhallErrors e
+ Dhall.Marshal.Decode: ExpectedTypeError :: ExpectedTypeError -> ExtractError s a
+ Dhall.Marshal.Decode: ExtractError :: Text -> ExtractError s a
+ Dhall.Marshal.Decode: InputNormalizer :: ReifiedNormalizer Void -> InputNormalizer
+ Dhall.Marshal.Decode: InterpretOptions :: (Text -> Text) -> (Text -> Text) -> SingletonConstructors -> InterpretOptions
+ Dhall.Marshal.Decode: InvalidDecoder :: Expr s a -> Expr s a -> InvalidDecoder s a
+ Dhall.Marshal.Decode: RecordDecoder :: Product (Const (Map Text (Expector (Expr Src Void)))) (Compose ((->) (Expr Src Void)) (Extractor Src Void)) a -> RecordDecoder a
+ Dhall.Marshal.Decode: RecursiveTypeError :: ExpectedTypeError
+ Dhall.Marshal.Decode: Smart :: SingletonConstructors
+ Dhall.Marshal.Decode: TypeMismatch :: InvalidDecoder s a -> ExtractError s a
+ Dhall.Marshal.Decode: UnionDecoder :: Compose (Map Text) Decoder a -> UnionDecoder a
+ Dhall.Marshal.Decode: Wrapped :: SingletonConstructors
+ Dhall.Marshal.Decode: [constructorModifier] :: InterpretOptions -> Text -> Text
+ Dhall.Marshal.Decode: [expected] :: Decoder a -> Expector (Expr Src Void)
+ Dhall.Marshal.Decode: [extract] :: Decoder a -> Expr Src Void -> Extractor Src Void a
+ Dhall.Marshal.Decode: [fieldModifier] :: InterpretOptions -> Text -> Text
+ Dhall.Marshal.Decode: [getErrors] :: DhallErrors e -> NonEmpty e
+ Dhall.Marshal.Decode: [getInputNormalizer] :: InputNormalizer -> ReifiedNormalizer Void
+ Dhall.Marshal.Decode: [invalidDecoderExpected] :: InvalidDecoder s a -> Expr s a
+ Dhall.Marshal.Decode: [invalidDecoderExpression] :: InvalidDecoder s a -> Expr s a
+ Dhall.Marshal.Decode: [singletonConstructors] :: InterpretOptions -> SingletonConstructors
+ Dhall.Marshal.Decode: auto :: FromDhall a => Decoder a
+ Dhall.Marshal.Decode: autoWith :: (FromDhall a, Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a
+ Dhall.Marshal.Decode: bool :: Decoder Bool
+ Dhall.Marshal.Decode: class FromDhall a
+ Dhall.Marshal.Decode: class Generic a
+ Dhall.Marshal.Decode: class GenericFromDhall t f
+ Dhall.Marshal.Decode: class GenericFromDhallUnion t f
+ Dhall.Marshal.Decode: constructor :: Text -> Decoder a -> UnionDecoder a
+ Dhall.Marshal.Decode: data Decoder a
+ Dhall.Marshal.Decode: data ExpectedTypeError
+ Dhall.Marshal.Decode: data ExtractError s a
+ Dhall.Marshal.Decode: data InterpretOptions
+ Dhall.Marshal.Decode: data InvalidDecoder s a
+ Dhall.Marshal.Decode: data Natural
+ Dhall.Marshal.Decode: data Result f
+ Dhall.Marshal.Decode: data Seq a
+ Dhall.Marshal.Decode: data SingletonConstructors
+ Dhall.Marshal.Decode: data Text
+ Dhall.Marshal.Decode: data Vector a
+ Dhall.Marshal.Decode: defaultInputNormalizer :: InputNormalizer
+ Dhall.Marshal.Decode: defaultInterpretOptions :: InterpretOptions
+ Dhall.Marshal.Decode: double :: Decoder Double
+ Dhall.Marshal.Decode: extractError :: Text -> Extractor s a b
+ Dhall.Marshal.Decode: field :: Text -> Decoder a -> RecordDecoder a
+ Dhall.Marshal.Decode: fromMonadic :: MonadicExtractor s a b -> Extractor s a b
+ Dhall.Marshal.Decode: function :: Encoder a -> Decoder b -> Decoder (a -> b)
+ Dhall.Marshal.Decode: functionWith :: InputNormalizer -> Encoder a -> Decoder b -> Decoder (a -> b)
+ Dhall.Marshal.Decode: genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a
+ Dhall.Marshal.Decode: genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a
+ Dhall.Marshal.Decode: genericAutoWithNormalizer :: GenericFromDhall t f => Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))
+ Dhall.Marshal.Decode: genericUnionAutoWithNormalizer :: GenericFromDhallUnion t f => Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)
+ Dhall.Marshal.Decode: hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)
+ Dhall.Marshal.Decode: hashSetFromDistinctList :: (Hashable a, Ord a, Show a) => Decoder a -> Decoder (HashSet a)
+ Dhall.Marshal.Decode: hashSetIgnoringDuplicates :: (Hashable a, Ord a) => Decoder a -> Decoder (HashSet a)
+ Dhall.Marshal.Decode: instance (Dhall.Marshal.Decode.FromDhall a, Data.Hashable.Class.Hashable a, GHC.Classes.Ord a, GHC.Show.Show a) => Dhall.Marshal.Decode.FromDhall (Data.HashSet.Internal.HashSet a)
+ Dhall.Marshal.Decode: instance (Dhall.Marshal.Decode.FromDhall a, Dhall.Marshal.Decode.FromDhall b) => Dhall.Marshal.Decode.FromDhall (a, b)
+ Dhall.Marshal.Decode: instance (Dhall.Marshal.Decode.FromDhall a, GHC.Classes.Ord a, GHC.Show.Show a) => Dhall.Marshal.Decode.FromDhall (Data.Set.Internal.Set a)
+ Dhall.Marshal.Decode: instance (Dhall.Marshal.Encode.ToDhall a, Dhall.Marshal.Decode.FromDhall b) => Dhall.Marshal.Decode.FromDhall (a -> b)
+ Dhall.Marshal.Decode: instance (GHC.Base.Functor f, Dhall.Marshal.Decode.FromDhall (f (Dhall.Marshal.Internal.Result f))) => Dhall.Marshal.Decode.FromDhall (Data.Fix.Fix f)
+ Dhall.Marshal.Decode: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k, Dhall.Marshal.Decode.FromDhall k, Dhall.Marshal.Decode.FromDhall v) => Dhall.Marshal.Decode.FromDhall (Data.HashMap.Internal.HashMap k v)
+ Dhall.Marshal.Decode: instance (GHC.Classes.Ord k, Dhall.Marshal.Decode.FromDhall k, Dhall.Marshal.Decode.FromDhall v) => Dhall.Marshal.Decode.FromDhall (Data.Map.Internal.Map k v)
+ Dhall.Marshal.Decode: instance (GHC.Show.Show (Dhall.Marshal.Decode.DhallErrors e), Data.Typeable.Internal.Typeable e) => GHC.Exception.Type.Exception (Dhall.Marshal.Decode.DhallErrors e)
+ Dhall.Marshal.Decode: instance (Prettyprinter.Internal.Pretty s, Data.Typeable.Internal.Typeable s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable a) => GHC.Exception.Type.Exception (Dhall.Marshal.Decode.InvalidDecoder s a)
+ Dhall.Marshal.Decode: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Exception.Type.Exception (Dhall.Marshal.Decode.ExtractError s a)
+ Dhall.Marshal.Decode: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.Marshal.Decode.ExtractError s a)
+ Dhall.Marshal.Decode: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.Marshal.Decode.ExtractErrors s a)
+ Dhall.Marshal.Decode: instance (Prettyprinter.Internal.Pretty s, Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable a) => GHC.Show.Show (Dhall.Marshal.Decode.InvalidDecoder s a)
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall ()
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall (f (Dhall.Marshal.Internal.Result f)) => Dhall.Marshal.Decode.FromDhall (Dhall.Marshal.Internal.Result f)
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall Data.Scientific.Scientific
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall Data.Text.Internal.Lazy.Text
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall Data.Text.Internal.Text
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall Data.Void.Void
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Int.Int16
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Int.Int32
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Int.Int64
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Int.Int8
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Integer.Type.Integer
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Natural.Natural
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Types.Bool
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Types.Double
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Types.Int
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Types.Word
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Word.Word16
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Word.Word32
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Word.Word64
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall GHC.Word.Word8
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall [GHC.Types.Char]
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall a => Dhall.Marshal.Decode.FromDhall (Data.Sequence.Internal.Seq a)
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall a => Dhall.Marshal.Decode.FromDhall (Data.Vector.Vector a)
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall a => Dhall.Marshal.Decode.FromDhall (GHC.Maybe.Maybe a)
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.FromDhall a => Dhall.Marshal.Decode.FromDhall [a]
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.GenericFromDhall a (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.GenericFromDhall a1 (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
+ Dhall.Marshal.Decode: instance Dhall.Marshal.Decode.GenericFromDhall a2 (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
+ Dhall.Marshal.Decode: instance GHC.Base.Applicative Dhall.Marshal.Decode.RecordDecoder
+ Dhall.Marshal.Decode: instance GHC.Base.Functor Dhall.Marshal.Decode.Decoder
+ Dhall.Marshal.Decode: instance GHC.Base.Functor Dhall.Marshal.Decode.DhallErrors
+ Dhall.Marshal.Decode: instance GHC.Base.Functor Dhall.Marshal.Decode.RecordDecoder
+ Dhall.Marshal.Decode: instance GHC.Base.Functor Dhall.Marshal.Decode.UnionDecoder
+ Dhall.Marshal.Decode: instance GHC.Base.Monoid (Dhall.Marshal.Decode.UnionDecoder a)
+ Dhall.Marshal.Decode: instance GHC.Base.Semigroup (Dhall.Marshal.Decode.DhallErrors e)
+ Dhall.Marshal.Decode: instance GHC.Base.Semigroup (Dhall.Marshal.Decode.UnionDecoder a)
+ Dhall.Marshal.Decode: instance GHC.Classes.Eq Dhall.Marshal.Decode.ExpectedTypeError
+ Dhall.Marshal.Decode: instance GHC.Classes.Eq e => GHC.Classes.Eq (Dhall.Marshal.Decode.DhallErrors e)
+ Dhall.Marshal.Decode: instance GHC.Exception.Type.Exception Dhall.Marshal.Decode.ExpectedTypeError
+ Dhall.Marshal.Decode: instance GHC.Show.Show Dhall.Marshal.Decode.ExpectedTypeError
+ Dhall.Marshal.Decode: instance GHC.Show.Show Dhall.Marshal.Decode.ExpectedTypeErrors
+ Dhall.Marshal.Decode: instance forall k1 k2 (c1 :: GHC.Generics.Meta) (t :: k1) (f1 :: k2 -> *). (GHC.Generics.Constructor c1, Dhall.Marshal.Decode.GenericFromDhall t f1) => Dhall.Marshal.Decode.GenericFromDhallUnion t (GHC.Generics.M1 GHC.Generics.C c1 f1)
+ Dhall.Marshal.Decode: instance forall k1 k2 (s :: GHC.Generics.Meta) a (t :: k1) (f :: k2 -> *) (g :: k2 -> *) i. (GHC.Generics.Selector s, Dhall.Marshal.Decode.FromDhall a, Dhall.Marshal.Decode.GenericFromDhall t (f GHC.Generics.:*: g)) => Dhall.Marshal.Decode.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a) GHC.Generics.:*: (f GHC.Generics.:*: g))
+ Dhall.Marshal.Decode: instance forall k1 k2 (s :: GHC.Generics.Meta) a (t :: k1) i. (GHC.Generics.Selector s, Dhall.Marshal.Decode.FromDhall a) => Dhall.Marshal.Decode.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
+ Dhall.Marshal.Decode: instance forall k1 k2 (s1 :: GHC.Generics.Meta) (s2 :: GHC.Generics.Meta) a1 a2 (t :: k1) i1 i2. (GHC.Generics.Selector s1, GHC.Generics.Selector s2, Dhall.Marshal.Decode.FromDhall a1, Dhall.Marshal.Decode.FromDhall a2) => Dhall.Marshal.Decode.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (c :: GHC.Generics.Meta). Dhall.Marshal.Decode.GenericFromDhall t f => Dhall.Marshal.Decode.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.C c f)
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (d :: GHC.Generics.Meta). Dhall.Marshal.Decode.GenericFromDhall t f => Dhall.Marshal.Decode.GenericFromDhall t (GHC.Generics.M1 GHC.Generics.D d f)
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *) (h :: k2 -> *) (i :: k2 -> *). (Dhall.Marshal.Decode.GenericFromDhall t (f GHC.Generics.:*: g), Dhall.Marshal.Decode.GenericFromDhall t (h GHC.Generics.:*: i)) => Dhall.Marshal.Decode.GenericFromDhall t ((f GHC.Generics.:*: g) GHC.Generics.:*: (h GHC.Generics.:*: i))
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *) (s :: GHC.Generics.Meta) a i. (Dhall.Marshal.Decode.GenericFromDhall t (f GHC.Generics.:*: g), GHC.Generics.Selector s, Dhall.Marshal.Decode.FromDhall a) => Dhall.Marshal.Decode.GenericFromDhall t ((f GHC.Generics.:*: g) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f :: k2 -> *) (g :: k2 -> *). Dhall.Marshal.Decode.GenericFromDhallUnion t (f GHC.Generics.:+: g) => Dhall.Marshal.Decode.GenericFromDhall t (f GHC.Generics.:+: g)
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1) (f1 :: k2 -> *) (f2 :: k2 -> *). (Dhall.Marshal.Decode.GenericFromDhallUnion t f1, Dhall.Marshal.Decode.GenericFromDhallUnion t f2) => Dhall.Marshal.Decode.GenericFromDhallUnion t (f1 GHC.Generics.:+: f2)
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1). Dhall.Marshal.Decode.GenericFromDhall t GHC.Generics.U1
+ Dhall.Marshal.Decode: instance forall k1 k2 (t :: k1). Dhall.Marshal.Decode.GenericFromDhall t GHC.Generics.V1
+ Dhall.Marshal.Decode: int :: Decoder Int
+ Dhall.Marshal.Decode: int16 :: Decoder Int16
+ Dhall.Marshal.Decode: int32 :: Decoder Int32
+ Dhall.Marshal.Decode: int64 :: Decoder Int64
+ Dhall.Marshal.Decode: int8 :: Decoder Int8
+ Dhall.Marshal.Decode: integer :: Decoder Integer
+ Dhall.Marshal.Decode: lazyText :: Decoder Text
+ Dhall.Marshal.Decode: list :: Decoder a -> Decoder [a]
+ Dhall.Marshal.Decode: map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)
+ Dhall.Marshal.Decode: maybe :: Decoder a -> Decoder (Maybe a)
+ Dhall.Marshal.Decode: natural :: Decoder Natural
+ Dhall.Marshal.Decode: newtype DhallErrors e
+ Dhall.Marshal.Decode: newtype InputNormalizer
+ Dhall.Marshal.Decode: newtype RecordDecoder a
+ Dhall.Marshal.Decode: newtype UnionDecoder a
+ Dhall.Marshal.Decode: pair :: Decoder a -> Decoder b -> Decoder (a, b)
+ Dhall.Marshal.Decode: pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)
+ Dhall.Marshal.Decode: record :: RecordDecoder a -> Decoder a
+ Dhall.Marshal.Decode: scientific :: Decoder Scientific
+ Dhall.Marshal.Decode: sequence :: Decoder a -> Decoder (Seq a)
+ Dhall.Marshal.Decode: setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Set a)
+ Dhall.Marshal.Decode: setIgnoringDuplicates :: Ord a => Decoder a -> Decoder (Set a)
+ Dhall.Marshal.Decode: showDhallErrors :: Show e => String -> DhallErrors e -> String
+ Dhall.Marshal.Decode: strictText :: Decoder Text
+ Dhall.Marshal.Decode: string :: Decoder String
+ Dhall.Marshal.Decode: toMonadic :: Extractor s a b -> MonadicExtractor s a b
+ Dhall.Marshal.Decode: type ExpectedTypeErrors = DhallErrors ExpectedTypeError
+ Dhall.Marshal.Decode: type Expector = Validation ExpectedTypeErrors
+ Dhall.Marshal.Decode: type ExtractErrors s a = DhallErrors (ExtractError s a)
+ Dhall.Marshal.Decode: type Extractor s a = Validation (ExtractErrors s a)
+ Dhall.Marshal.Decode: type Interpret = FromDhall
+ Dhall.Marshal.Decode: type MonadicExtractor s a = Either (ExtractErrors s a)
+ Dhall.Marshal.Decode: typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b
+ Dhall.Marshal.Decode: union :: UnionDecoder a -> Decoder a
+ Dhall.Marshal.Decode: unit :: Decoder ()
+ Dhall.Marshal.Decode: vector :: Decoder a -> Decoder (Vector a)
+ Dhall.Marshal.Decode: void :: Decoder Void
+ Dhall.Marshal.Decode: word :: Decoder Word
+ Dhall.Marshal.Decode: word16 :: Decoder Word16
+ Dhall.Marshal.Decode: word32 :: Decoder Word32
+ Dhall.Marshal.Decode: word64 :: Decoder Word64
+ Dhall.Marshal.Decode: word8 :: Decoder Word8
+ Dhall.Marshal.Encode: (>$<) :: Contravariant f => (a -> b) -> f b -> f a
+ Dhall.Marshal.Encode: (>*<) :: Divisible f => f a -> f b -> f (a, b)
+ Dhall.Marshal.Encode: (>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)
+ Dhall.Marshal.Encode: Bare :: SingletonConstructors
+ Dhall.Marshal.Encode: Encoder :: (a -> Expr Src Void) -> Expr Src Void -> Encoder a
+ Dhall.Marshal.Encode: InputNormalizer :: ReifiedNormalizer Void -> InputNormalizer
+ Dhall.Marshal.Encode: InterpretOptions :: (Text -> Text) -> (Text -> Text) -> SingletonConstructors -> InterpretOptions
+ Dhall.Marshal.Encode: RecordEncoder :: Map Text (Encoder a) -> RecordEncoder a
+ Dhall.Marshal.Encode: Smart :: SingletonConstructors
+ Dhall.Marshal.Encode: UnionEncoder :: Product (Const (Map Text (Expr Src Void))) (Op (Text, Expr Src Void)) a -> UnionEncoder a
+ Dhall.Marshal.Encode: Wrapped :: SingletonConstructors
+ Dhall.Marshal.Encode: [constructorModifier] :: InterpretOptions -> Text -> Text
+ Dhall.Marshal.Encode: [declared] :: Encoder a -> Expr Src Void
+ Dhall.Marshal.Encode: [embed] :: Encoder a -> a -> Expr Src Void
+ Dhall.Marshal.Encode: [fieldModifier] :: InterpretOptions -> Text -> Text
+ Dhall.Marshal.Encode: [getInputNormalizer] :: InputNormalizer -> ReifiedNormalizer Void
+ Dhall.Marshal.Encode: [singletonConstructors] :: InterpretOptions -> SingletonConstructors
+ Dhall.Marshal.Encode: class Generic a
+ Dhall.Marshal.Encode: class GenericToDhall f
+ Dhall.Marshal.Encode: class ToDhall a
+ Dhall.Marshal.Encode: data Encoder a
+ Dhall.Marshal.Encode: data InterpretOptions
+ Dhall.Marshal.Encode: data Natural
+ Dhall.Marshal.Encode: data Result f
+ Dhall.Marshal.Encode: data Seq a
+ Dhall.Marshal.Encode: data SingletonConstructors
+ Dhall.Marshal.Encode: data Text
+ Dhall.Marshal.Encode: data Vector a
+ Dhall.Marshal.Encode: defaultInputNormalizer :: InputNormalizer
+ Dhall.Marshal.Encode: defaultInterpretOptions :: InterpretOptions
+ Dhall.Marshal.Encode: encodeConstructor :: ToDhall a => Text -> UnionEncoder a
+ Dhall.Marshal.Encode: encodeConstructorWith :: Text -> Encoder a -> UnionEncoder a
+ Dhall.Marshal.Encode: encodeField :: ToDhall a => Text -> RecordEncoder a
+ Dhall.Marshal.Encode: encodeFieldWith :: Text -> Encoder a -> RecordEncoder a
+ Dhall.Marshal.Encode: genericToDhall :: (Generic a, GenericToDhall (Rep a)) => Encoder a
+ Dhall.Marshal.Encode: genericToDhallWith :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a
+ Dhall.Marshal.Encode: genericToDhallWithNormalizer :: GenericToDhall f => InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))
+ Dhall.Marshal.Encode: infixl 4 >$<
+ Dhall.Marshal.Encode: infixr 5 >*<
+ Dhall.Marshal.Encode: inject :: ToDhall a => Encoder a
+ Dhall.Marshal.Encode: injectWith :: (ToDhall a, Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.GenericToDhall (f GHC.Generics.:*: g), Dhall.Marshal.Encode.GenericToDhall (h GHC.Generics.:*: i)) => Dhall.Marshal.Encode.GenericToDhall ((f GHC.Generics.:*: g) GHC.Generics.:*: (h GHC.Generics.:*: i))
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.GenericToDhall (f GHC.Generics.:*: g), GHC.Generics.Selector s, Dhall.Marshal.Encode.ToDhall a) => Dhall.Marshal.Encode.GenericToDhall ((f GHC.Generics.:*: g) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.GenericToDhall (f GHC.Generics.:+: g), Dhall.Marshal.Encode.GenericToDhall (h GHC.Generics.:+: i)) => Dhall.Marshal.Encode.GenericToDhall ((f GHC.Generics.:+: g) GHC.Generics.:+: (h GHC.Generics.:+: i))
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.ToDhall a, Dhall.Marshal.Encode.ToDhall b) => Dhall.Marshal.Encode.ToDhall (a, b)
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.ToDhall k, Dhall.Marshal.Encode.ToDhall v) => Dhall.Marshal.Encode.ToDhall (Data.HashMap.Internal.HashMap k v)
+ Dhall.Marshal.Encode: instance (Dhall.Marshal.Encode.ToDhall k, Dhall.Marshal.Encode.ToDhall v) => Dhall.Marshal.Encode.ToDhall (Data.Map.Internal.Map k v)
+ Dhall.Marshal.Encode: instance (GHC.Base.Functor f, Dhall.Marshal.Encode.ToDhall (f (Dhall.Marshal.Internal.Result f))) => Dhall.Marshal.Encode.ToDhall (Data.Fix.Fix f)
+ Dhall.Marshal.Encode: instance (GHC.Generics.Constructor c, Dhall.Marshal.Encode.GenericToDhall (f GHC.Generics.:+: g), Dhall.Marshal.Encode.GenericToDhall h) => Dhall.Marshal.Encode.GenericToDhall ((f GHC.Generics.:+: g) GHC.Generics.:+: GHC.Generics.M1 GHC.Generics.C c h)
+ Dhall.Marshal.Encode: instance (GHC.Generics.Constructor c, Dhall.Marshal.Encode.GenericToDhall f, Dhall.Marshal.Encode.GenericToDhall (g GHC.Generics.:+: h)) => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c f GHC.Generics.:+: (g GHC.Generics.:+: h))
+ Dhall.Marshal.Encode: instance (GHC.Generics.Constructor c1, GHC.Generics.Constructor c2, Dhall.Marshal.Encode.GenericToDhall f1, Dhall.Marshal.Encode.GenericToDhall f2) => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c1 f1 GHC.Generics.:+: GHC.Generics.M1 GHC.Generics.C c2 f2)
+ Dhall.Marshal.Encode: instance (GHC.Generics.Selector s, Dhall.Marshal.Encode.ToDhall a) => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a))
+ Dhall.Marshal.Encode: instance (GHC.Generics.Selector s, Dhall.Marshal.Encode.ToDhall a, Dhall.Marshal.Encode.GenericToDhall (f GHC.Generics.:*: g)) => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a) GHC.Generics.:*: (f GHC.Generics.:*: g))
+ Dhall.Marshal.Encode: instance (GHC.Generics.Selector s1, GHC.Generics.Selector s2, Dhall.Marshal.Encode.ToDhall a1, Dhall.Marshal.Encode.ToDhall a2) => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.S s1 (GHC.Generics.K1 i1 a1) GHC.Generics.:*: GHC.Generics.M1 GHC.Generics.S s2 (GHC.Generics.K1 i2 a2))
+ Dhall.Marshal.Encode: instance Data.Functor.Contravariant.Contravariant Dhall.Marshal.Encode.Encoder
+ Dhall.Marshal.Encode: instance Data.Functor.Contravariant.Contravariant Dhall.Marshal.Encode.RecordEncoder
+ Dhall.Marshal.Encode: instance Data.Functor.Contravariant.Contravariant Dhall.Marshal.Encode.UnionEncoder
+ Dhall.Marshal.Encode: instance Data.Functor.Contravariant.Divisible.Divisible Dhall.Marshal.Encode.RecordEncoder
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.GenericToDhall GHC.Generics.U1
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.GenericToDhall f => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.C c f)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.GenericToDhall f => Dhall.Marshal.Encode.GenericToDhall (GHC.Generics.M1 GHC.Generics.D d f)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall ()
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall (f (Dhall.Marshal.Internal.Result f)) => Dhall.Marshal.Encode.ToDhall (Dhall.Marshal.Internal.Result f)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall Data.Scientific.Scientific
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall Data.Text.Internal.Lazy.Text
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall Data.Text.Internal.Text
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall Data.Void.Void
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Base.String
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Integer.Type.Integer
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Natural.Natural
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Types.Bool
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Types.Double
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Types.Int
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Types.Word
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Word.Word16
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Word.Word32
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Word.Word64
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall GHC.Word.Word8
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall (Data.HashSet.Internal.HashSet a)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall (Data.Sequence.Internal.Seq a)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall (Data.Set.Internal.Set a)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall (Data.Vector.Vector a)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall (GHC.Maybe.Maybe a)
+ Dhall.Marshal.Encode: instance Dhall.Marshal.Encode.ToDhall a => Dhall.Marshal.Encode.ToDhall [a]
+ Dhall.Marshal.Encode: newtype InputNormalizer
+ Dhall.Marshal.Encode: newtype RecordEncoder a
+ Dhall.Marshal.Encode: newtype UnionEncoder a
+ Dhall.Marshal.Encode: recordEncoder :: RecordEncoder a -> Encoder a
+ Dhall.Marshal.Encode: type Inject = ToDhall
+ Dhall.Marshal.Encode: unionEncoder :: UnionEncoder a -> Encoder a
+ Dhall.Parser.Token: endOfLine :: Parser Text
+ Dhall.TH: dhall :: QuasiQuoter
+ Dhall.Util: MultipleCheckFailed :: Text -> Text -> NonEmpty Input -> MultipleCheckFailed
+ Dhall.Util: [input] :: CheckFailed -> Input
+ Dhall.Util: [inputs] :: MultipleCheckFailed -> NonEmpty Input
+ Dhall.Util: data MultipleCheckFailed
+ Dhall.Util: handleMultipleChecksFailed :: (Foldable t, Traversable t) => Text -> Text -> (a -> IO (Either CheckFailed ())) -> t a -> IO ()
+ Dhall.Util: instance GHC.Classes.Eq Dhall.Util.Input
+ Dhall.Util: instance GHC.Exception.Type.Exception Dhall.Util.MultipleCheckFailed
+ Dhall.Util: instance GHC.Show.Show Dhall.Util.MultipleCheckFailed
+ Dhall.Util: newtype CheckFailed
- Dhall.Core: Equivalent :: Expr s a -> Expr s a -> Expr s a
+ Dhall.Core: Equivalent :: Maybe CharacterSet -> Expr s a -> Expr s a -> Expr s a
- Dhall.Format: Format :: Maybe CharacterSet -> Censor -> PossiblyTransitiveInput -> OutputMode -> Format
+ Dhall.Format: Format :: Maybe CharacterSet -> Censor -> Transitivity -> NonEmpty Input -> OutputMode -> Format
- Dhall.Freeze: freeze :: OutputMode -> PossiblyTransitiveInput -> Scope -> Intent -> Maybe CharacterSet -> Censor -> IO ()
+ Dhall.Freeze: freeze :: OutputMode -> Transitivity -> NonEmpty Input -> Scope -> Intent -> Maybe CharacterSet -> Censor -> IO ()
- Dhall.Freeze: freezeWithManager :: IO Manager -> OutputMode -> PossiblyTransitiveInput -> Scope -> Intent -> Maybe CharacterSet -> Censor -> IO ()
+ Dhall.Freeze: freezeWithManager :: IO Manager -> OutputMode -> Transitivity -> NonEmpty Input -> Scope -> Intent -> Maybe CharacterSet -> Censor -> IO ()
- Dhall.Main: Format :: PossiblyTransitiveInput -> OutputMode -> Mode
+ Dhall.Main: Format :: Bool -> Transitivity -> OutputMode -> NonEmpty Input -> Mode
- Dhall.Main: Freeze :: PossiblyTransitiveInput -> Bool -> Bool -> OutputMode -> Mode
+ Dhall.Main: Freeze :: Bool -> Transitivity -> Bool -> Bool -> OutputMode -> NonEmpty Input -> Mode
- Dhall.Main: Lint :: PossiblyTransitiveInput -> OutputMode -> Mode
+ Dhall.Main: Lint :: Bool -> Transitivity -> OutputMode -> NonEmpty Input -> Mode
- Dhall.Parser.Token: _equivalent :: Parser ()
+ Dhall.Parser.Token: _equivalent :: Parser CharacterSet
- Dhall.Util: CheckFailed :: Text -> Text -> CheckFailed
+ Dhall.Util: CheckFailed :: Input -> CheckFailed
- Dhall.Util: [command] :: CheckFailed -> Text
+ Dhall.Util: [command] :: MultipleCheckFailed -> Text
- Dhall.Util: [modified] :: CheckFailed -> Text
+ Dhall.Util: [modified] :: MultipleCheckFailed -> Text
- Dhall.Util: getExpressionAndHeaderFromStdinText :: Censor -> Text -> IO (Header, Expr Src Import)
+ Dhall.Util: getExpressionAndHeaderFromStdinText :: Censor -> String -> Text -> IO (Header, Expr Src Import)
Files
- CHANGELOG.md +34/−0
- dhall-lang/Prelude/List/fold.dhall +17/−25
- dhall-lang/Prelude/List/foldLeft.dhall +60/−0
- dhall-lang/Prelude/List/package.dhall +3/−0
- dhall-lang/Prelude/Natural/fold.dhall +8/−15
- dhall-lang/Prelude/Optional/fold.dhall +2/−3
- dhall-lang/Prelude/Text/lowerASCII.dhall +56/−0
- dhall-lang/Prelude/Text/package.dhall +6/−0
- dhall-lang/Prelude/Text/upperASCII.dhall +56/−0
- dhall-lang/Prelude/XML/package.dhall +1/−1
- dhall-lang/Prelude/XML/render +1/−1
- dhall-lang/Prelude/XML/render.dhall +14/−12
- dhall-lang/Prelude/package.dhall +3/−3
- dhall-lang/tests/import/data/cycle.dhall +1/−1
- dhall-lang/tests/import/failure/cycle.dhall +0/−1
- dhall-lang/tests/import/failure/hashMismatch.dhall +0/−1
- dhall-lang/tests/import/failure/importBoundary.dhall +0/−1
- dhall-lang/tests/import/failure/missing.dhall +0/−1
- dhall-lang/tests/import/failure/referentiallyInsane.dhall +0/−13
- dhall-lang/tests/import/failure/unit/404.dhall +1/−0
- dhall-lang/tests/import/failure/unit/Cycle.dhall +1/−0
- dhall-lang/tests/import/failure/unit/DontRecoverCycle.dhall +1/−0
- dhall-lang/tests/import/failure/unit/DontRecoverTypeError.dhall +1/−0
- dhall-lang/tests/import/failure/unit/EnvFromRemote.dhall +13/−0
- dhall-lang/tests/import/failure/unit/FileMissing.dhall +1/−0
- dhall-lang/tests/import/failure/unit/HashMismatch.dhall +1/−0
- dhall-lang/tests/import/failure/unit/HashMismatch2.dhall +2/−0
- dhall-lang/tests/import/failure/unit/Missing.dhall +1/−0
- dhall-lang/tests/import/failure/unit/VarAcrossImportBoundary.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithVariableA.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithVariableB.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1A.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1B.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2A.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2B.dhall +1/−0
- dhall-lang/tests/import/success/unit/DontCacheIfHashA.dhall +5/−0
- dhall-lang/tests/import/success/unit/DontCacheIfHashB.dhall +1/−0
- dhall-lang/tests/import/success/unit/MixImportModesA.dhall +2/−0
- dhall-lang/tests/import/success/unit/MixImportModesB.dhall +1/−0
- dhall-lang/tests/import/success/unit/RecoverTransitiveFailureA.dhall +1/−0
- dhall-lang/tests/import/success/unit/RecoverTransitiveFailureB.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationA.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationB.dhall +3/−0
- dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordSortFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordSortFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1A.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1B.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2A.dhall +2/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2B.dhall +2/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3A.dhall +3/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3B.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmptyA.dhall +0/−3
- dhall-lang/tests/normalization/success/unit/TextReplaceEmptyB.dhall +0/−1
- dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingB.dhall +1/−0
- dhall-lang/tests/parser/success/unit/ShebangA.dhall +2/−0
- dhall-lang/tests/parser/success/unit/ShebangB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/ShebangNixA.dhall +3/−0
- dhall-lang/tests/parser/success/unit/ShebangNixB.dhallb +1/−0
- dhall-lang/tests/type-inference/success/preludeB.dhall +9/−0
- dhall-lang/tests/type-inference/success/unit/WithInfersKindA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/WithInfersKindB.dhall +1/−0
- dhall.cabal +8/−5
- src/Dhall.hs +449/−2859
- src/Dhall/Binary.hs +5/−39
- src/Dhall/Diff.hs +1/−1
- src/Dhall/Eval.hs +53/−33
- src/Dhall/Format.hs +33/−28
- src/Dhall/Freeze.hs +26/−23
- src/Dhall/Import.hs +23/−33
- src/Dhall/Main.hs +67/−43
- src/Dhall/Marshal/Decode.hs +1492/−0
- src/Dhall/Marshal/Encode.hs +931/−0
- src/Dhall/Marshal/Internal.hs +188/−0
- src/Dhall/Normalize.hs +3/−3
- src/Dhall/Parser/Expression.hs +17/−8
- src/Dhall/Parser/Token.hs +12/−10
- src/Dhall/Pretty/Internal.hs +3/−2
- src/Dhall/Schemas.hs +8/−6
- src/Dhall/Syntax.hs +19/−10
- src/Dhall/TH.hs +19/−1
- src/Dhall/Tutorial.hs +3/−4
- src/Dhall/TypeCheck.hs +1/−1
- src/Dhall/Util.hs +60/−21
- tests/Dhall/Test/Import.hs +51/−18
- tests/format/ipfsB.dhall +2/−1
- tests/format/issue1400-2B.dhall +2/−1
- tests/format/sha256PrintingB.dhall +2/−1
- tests/freeze/cachedB.dhall +2/−1
- tests/freeze/incorrectHashB.dhall +2/−1
- tests/freeze/protectedB.dhall +2/−1
- tests/freeze/unprotectedB.dhall +2/−1
CHANGELOG.md view
@@ -1,3 +1,37 @@+1.39.0++* [Supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+ * [Add support for Unix shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2175)+* [BREAKING CHANGE TO THE API: `dhall {format,freeze,lint}` now accept multiple+ files](https://github.com/dhall-lang/dhall-haskell/pull/2169)+ * The `--inplace` flag is no longer necessary and you can now specify+ multiple files to update in place on the command line, like+ `dhall format foo.dhall bar.dhall`+ * The `--inplace` flag is still accepted, but does nothing, and will emit a+ warning+ * This is a breaking change to the API for formatting/freezing/linting files+ because now you can specify multiple inputs instead of one input+* [BREAKING CHANGE: Pre-6.0.0 hashes are no longer supported](https://github.com/dhall-lang/dhall-haskell/pull/2190)+ * The interpreter no longer provides backwards compatibility for integrity+ checks computed before standard version 6.0.0+ * This is a breaking change to the API of the `Dhall.Binary` module, where+ certain utilities are no longer parameterized on a `StandardVersion`+ * This is also a breaking change to any Dhall code that depended on these+ really old integrity checks+* [BUG FIX: Formatting `≡` now correctly preserves the original character set](https://github.com/dhall-lang/dhall-haskell/pull/2176)+* [BUG FIX: Don't panic on `Text/replace ""`](https://github.com/dhall-lang/dhall-haskell/pull/2184)+* [Quasiquotation support for Dhall](https://github.com/dhall-lang/dhall-haskell/pull/2198)+ * You can now convert a Dhall expression to the corresponding syntax tree+ using a quasiquoter like this: `[dhall| \x -> x + 2 ]`+* [New `Dhall.Marshal.{Encode,Decode}` modules](https://github.com/dhall-lang/dhall-haskell/pull/2193)+ * These modules split up the `Dhall` module into two smaller modules for+ encoding and decoding logic, respectively+ * The `Dhall` module still re-exports the same functionality as before, so+ this is not a breaking change+* [Support GHC 9.0.1](https://github.com/dhall-lang/dhall-haskell/pull/2154)+* Fixes and improvements to code formatting+ * [Improve pretty-printing of `sha256`](https://github.com/dhall-lang/dhall-haskell/pull/2189)+ 1.38.1 * [Add `INLINABLE` annotations in more places](https://github.com/dhall-lang/dhall-haskell/pull/2164)
dhall-lang/Prelude/List/fold.dhall view
@@ -18,34 +18,26 @@ : fold Natural [ 2, 3, 5 ]- Natural- (λ(x : Natural) → λ(y : Natural) → x + y)- 0- ≡ 10+ Text+ (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+ "0"+ ≡ "2350" let example1 =- assert- : ( λ(nil : Natural) →- fold- Natural- [ 2, 3, 5 ]- Natural- (λ(x : Natural) → λ(y : Natural) → x + y)- nil- )- ≡ (λ(nil : Natural) → 2 + (3 + (5 + nil)))+ λ(nil : Text) →+ assert+ : fold+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+ nil+ ≡ "2" ++ ("3" ++ ("5" ++ nil)) let example2 =- assert- : ( λ(list : Type) →- λ(cons : Natural → list → list) →- λ(nil : list) →- fold Natural [ 2, 3, 5 ] list cons nil- )- ≡ ( λ(list : Type) →- λ(cons : Natural → list → list) →- λ(nil : list) →- cons 2 (cons 3 (cons 5 nil))- )+ λ(cons : Natural → Text → Text) →+ λ(nil : Text) →+ assert+ : fold Natural [ 2, 3, 5 ] Text cons nil ≡ cons 2 (cons 3 (cons 5 nil)) in fold
+ dhall-lang/Prelude/List/foldLeft.dhall view
@@ -0,0 +1,60 @@+{-|+`foldLeft` is like `List/fold` except that the accumulation starts from the left++If you treat the list `[ x, y, z ]` as `cons (cons (cons nil x) y) z`, then+`foldLeft` just replaces each `cons` and `nil` with something else+-}+let foldLeft+ : ∀(a : Type) →+ List a →+ ∀(list : Type) →+ ∀(cons : list → a → list) →+ ∀(nil : list) →+ list+ = λ(a : Type) →+ λ(xs : List a) →+ λ(list : Type) →+ λ(cons : list → a → list) →+ λ(nil : list) →+ List/fold+ a+ xs+ (list → list)+ (λ(x : a) → λ(f : list → list) → λ(l : list) → f (cons l x))+ (λ(l : list) → l)+ nil++let example0 =+ assert+ : foldLeft+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+ "0"+ ≡ "0235"++let example1 =+ assert+ : ( λ(nil : Text) →+ foldLeft+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+ nil+ )+ ≡ (λ(nil : Text) → nil ++ "2" ++ "3" ++ "5")++let example2 =+ assert+ : ( λ(cons : Text → Natural → Text) →+ λ(nil : Text) →+ foldLeft Natural [ 2, 3, 5 ] Text cons nil+ )+ ≡ ( λ(cons : Text → Natural → Text) →+ λ(nil : Text) →+ cons (cons (cons nil 2) 3) 5+ )++in foldLeft
dhall-lang/Prelude/List/package.dhall view
@@ -28,6 +28,9 @@ , fold = ./fold.dhall sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814 ? ./fold.dhall+, foldLeft =+ ./foldLeft.dhall sha256:3c6ab57950fe644906b7bbdef0b9523440b6ee17773ebb8cbd41ffacb8bfab61+ ? ./foldLeft.dhall , generate = ./generate.dhall sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4 ? ./generate.dhall
dhall-lang/Prelude/Natural/fold.dhall view
@@ -12,24 +12,17 @@ natural = Natural/fold -let example0 = assert : fold 3 Natural (λ(x : Natural) → 5 * x) 1 ≡ 125+let example0 = assert : fold 3 Text (λ(x : Text) → "A" ++ x) "B" ≡ "AAAB" let example1 =- assert- : (λ(zero : Natural) → fold 3 Natural (λ(x : Natural) → 5 * x) zero)- ≡ (λ(zero : Natural) → 5 * (5 * (5 * zero)))+ λ(zero : Text) →+ assert+ : fold 3 Text (λ(x : Text) → "A" ++ x) zero+ ≡ "A" ++ ("A" ++ ("A" ++ zero)) let example2 =- assert- : ( λ(natural : Type) →- λ(succ : natural → natural) →- λ(zero : natural) →- fold 3 natural succ zero- )- ≡ ( λ(natural : Type) →- λ(succ : natural → natural) →- λ(zero : natural) →- succ (succ (succ zero))- )+ λ(succ : Text → Text) →+ λ(zero : Text) →+ assert : fold 3 Text succ zero ≡ succ (succ (succ zero)) in fold
dhall-lang/Prelude/Optional/fold.dhall view
@@ -13,9 +13,8 @@ λ(none : optional) → merge { Some = some, None = none } o -let example0 = assert : fold Natural (Some 2) Natural (λ(x : Natural) → x) 0 ≡ 2+let example0 = assert : fold Natural (Some 2) Text Natural/show "0" ≡ "2" -let example1 =- assert : fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 ≡ 0+let example1 = assert : fold Natural (None Natural) Text Natural/show "0" ≡ "0" in fold
+ dhall-lang/Prelude/Text/lowerASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Lowercase all ASCII characters++Note that this will also lowercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let lowerASCII+ : Text → Text+ = List/fold+ (Text → Text)+ [ Text/replace "A" "a"+ , Text/replace "B" "b"+ , Text/replace "C" "c"+ , Text/replace "D" "d"+ , Text/replace "E" "e"+ , Text/replace "F" "f"+ , Text/replace "G" "g"+ , Text/replace "H" "h"+ , Text/replace "I" "i"+ , Text/replace "J" "j"+ , Text/replace "K" "k"+ , Text/replace "L" "l"+ , Text/replace "M" "m"+ , Text/replace "N" "n"+ , Text/replace "O" "o"+ , Text/replace "P" "p"+ , Text/replace "Q" "q"+ , Text/replace "R" "r"+ , Text/replace "S" "s"+ , Text/replace "T" "t"+ , Text/replace "U" "u"+ , Text/replace "V" "v"+ , Text/replace "W" "w"+ , Text/replace "X" "x"+ , Text/replace "Y" "y"+ , Text/replace "Z" "z"+ ]+ Text+ (λ(replacement : Text → Text) → replacement)++let example0 = assert : lowerASCII "ABCdef" ≡ "abcdef"++let -- This does not lowercase precomposed Unicode characters+ --+ -- • The `Á` in the following example is U+00C1+ example1 =+ assert : lowerASCII "Á" ≡ "Á"++let -- … but this does lowercase decomposed Unicode characters+ --+ -- • The `Á` in the following example is U+0041 U+0301+ -- • The `á` in the following example is U+0061 U+0301+ example1 =+ assert : lowerASCII "Á" ≡ "á"++in lowerASCII
dhall-lang/Prelude/Text/package.dhall view
@@ -16,6 +16,9 @@ , defaultMap = ./defaultMap.dhall sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588 ? ./defaultMap.dhall+, lowerASCII =+ ./lowerASCII.dhall sha256:26b076651120b907e869396bd3dc16271f2e12433062b2f26f296968a69515e7+ ? ./lowerASCII.dhall , replace = ./replace.dhall sha256:7d132df0e091a43817bba8afa06d1bb487ee51c091430404ad6f8c78bc0328a6 ? ./replace.dhall@@ -28,4 +31,7 @@ , spaces = ./spaces.dhall sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc ? ./spaces.dhall+, upperASCII =+ ./upperASCII.dhall sha256:45ae4fbd814b0474e65c28a4ee92b23b979892fa5bb73730bc99675ae790ca29+ ? ./upperASCII.dhall }
+ dhall-lang/Prelude/Text/upperASCII.dhall view
@@ -0,0 +1,56 @@+{-|+Uppercase all ASCII characters++Note that this will also uppercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let upperASCII+ : Text → Text+ = List/fold+ (Text → Text)+ [ Text/replace "a" "A"+ , Text/replace "b" "B"+ , Text/replace "c" "C"+ , Text/replace "d" "D"+ , Text/replace "e" "E"+ , Text/replace "f" "F"+ , Text/replace "g" "G"+ , Text/replace "h" "H"+ , Text/replace "i" "I"+ , Text/replace "j" "J"+ , Text/replace "k" "K"+ , Text/replace "l" "L"+ , Text/replace "m" "M"+ , Text/replace "n" "N"+ , Text/replace "o" "O"+ , Text/replace "p" "P"+ , Text/replace "q" "Q"+ , Text/replace "r" "R"+ , Text/replace "s" "S"+ , Text/replace "t" "T"+ , Text/replace "u" "U"+ , Text/replace "v" "V"+ , Text/replace "w" "W"+ , Text/replace "x" "X"+ , Text/replace "y" "Y"+ , Text/replace "z" "Z"+ ]+ Text+ (λ(replacement : Text → Text) → replacement)++let example0 = assert : upperASCII "ABCdef" ≡ "ABCDEF"++let -- This does not uppercase precomposed Unicode characters+ --+ -- • The `á` in the following example is U+00E1+ example1 =+ assert : upperASCII "á" ≡ "á"++let -- … but this does uppercase decomposed Unicode characters+ --+ -- • The `Á` in the following example is U+0041 U+0301+ -- • The `á` in the following example is U+0061 U+0301+ example1 =+ assert : upperASCII "á" ≡ "Á"++in upperASCII
dhall-lang/Prelude/XML/package.dhall view
@@ -5,7 +5,7 @@ ./attribute.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./attribute.dhall , render =- ./render.dhall sha256:aff7efe61ce299381edca023e24bb5aaa0656c41bfa45dd705dab63519b7c5db+ ./render.dhall sha256:550c8900fe199b83d629181d53c646f2f9425d9c64670dabb30d28e95bfa4c75 ? ./render.dhall , element = ./element.dhall sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b
dhall-lang/Prelude/XML/render view
@@ -1,2 +1,2 @@- ./render.dhall sha256:aff7efe61ce299381edca023e24bb5aaa0656c41bfa45dd705dab63519b7c5db+ ./render.dhall sha256:550c8900fe199b83d629181d53c646f2f9425d9c64670dabb30d28e95bfa4c75 ? ./render.dhall
dhall-lang/Prelude/XML/render.dhall view
@@ -1,10 +1,6 @@ {-| Render an `XML` value as `Text` -*WARNING:* rendering does not include any XML injection mitigations,-therefore it should not be used to process arbitrary strings into-element attributes or element data.- For indentation and schema validation, see the `xmllint` utility bundled with libxml2. @@ -48,16 +44,24 @@ let Attr = { mapKey : Text, mapValue : Text } -let `escape"` = Text/replace "\"" "\\\""+let esc = λ(x : Text) → λ(y : Text) → Text/replace x "&${y};" -let `escape<` = Text/replace "<" "\\<"+let `escape&` = esc "&" "amp" -let `escape&` = Text/replace "&" "\\&"+let `escape<` = esc "<" "lt" -let escapeText = λ(text : Text) → `escape<` (`escape&` text)+let `escape>` = esc ">" "gt" -let escapeAttr = λ(text : Text) → `escape"` (`escape<` (`escape&` text))+let `escape'` = esc "'" "apos" +let `escape"` = esc "\"" "quot"++let escapeCommon = λ(text : Text) → `escape<` (`escape&` text)++let escapeAttr = λ(text : Text) → `escape"` (`escape'` (escapeCommon text))++let escapeText = λ(text : Text) → `escape>` (escapeCommon text)+ let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${escapeAttr x.mapValue}\"" let render@@ -123,9 +127,7 @@ "\n" "" ''- <escape attribute="\<>'\"\&">- \<>'"\&- </escape>+ <escape attribute="<>'"&"><>'"&</escape> '' in render
dhall-lang/Prelude/package.dhall view
@@ -11,7 +11,7 @@ ./Integer/package.dhall sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0 ? ./Integer/package.dhall , List =- ./List/package.dhall sha256:547cd881988c6c5e3673ae80491224158e93a4627690db0196cb5efbbf00d2ba+ ./List/package.dhall sha256:11081c23436cb9c5fa60d53416e62845071990b43b3c48973cb2f19f5d5adbee ? ./List/package.dhall , Location = ./Location/package.dhall sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470@@ -35,9 +35,9 @@ ./JSON/package.dhall sha256:5f98b7722fd13509ef448b075e02b9ff98312ae7a406cf53ed25012dbc9990ac ? ./JSON/package.dhall , Text =- ./Text/package.dhall sha256:46c53957c10bd4c332a5716d6e06068cd24ae1392ca171e6da31e30b9b33c07c+ ./Text/package.dhall sha256:17a0e0e881b05436d7e3ae94a658af9da5ba2a921fafa0d1d545890978853434 ? ./Text/package.dhall , XML =- ./XML/package.dhall sha256:8f57bda3087cbb34568d58e5dd5ee6860a50576caf48ebe49a5fc60b9af9a1fa+ ./XML/package.dhall sha256:6a15ea2ab1918f97374ec2fe3b90c056fb807fb3a90c1c44ce9fb9233f59c0e5 ? ./XML/package.dhall }
dhall-lang/tests/import/data/cycle.dhall view
@@ -1,1 +1,1 @@-../failure/cycle.dhall+../failure/unit/Cycle.dhall
− dhall-lang/tests/import/failure/cycle.dhall
@@ -1,1 +0,0 @@-../data/cycle.dhall
− dhall-lang/tests/import/failure/hashMismatch.dhall
@@ -1,1 +0,0 @@-../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
− dhall-lang/tests/import/failure/importBoundary.dhall
@@ -1,1 +0,0 @@-\(x: Bool) -> ../data/importBoundary.dhall
− dhall-lang/tests/import/failure/missing.dhall
@@ -1,1 +0,0 @@-missing
− dhall-lang/tests/import/failure/referentiallyInsane.dhall
@@ -1,13 +0,0 @@-{- The following remote import attempts to import an environment variable, which- must be disallowed by the referential sanity check-- One reason for doing this is to protect against remote imports exfiltrating- environment variables (such as via custom headers). Only referentially- opaque imports (i.e. local imports) have permission to refer to other- referentially opaque imports in order to protect against this attack.-- The referential sanity check also ensures that remote imports are- referentially transparent. Or in other words, any import that is globally- addressable must have a meaning that is not context-sensitive.--}-https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/data/referentiallyOpaque.dhall
+ dhall-lang/tests/import/failure/unit/404.dhall view
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/nonexistent-file.dhall
+ dhall-lang/tests/import/failure/unit/Cycle.dhall view
@@ -0,0 +1,1 @@+../../data/cycle.dhall
+ dhall-lang/tests/import/failure/unit/DontRecoverCycle.dhall view
@@ -0,0 +1,1 @@+./cycle.dhall ? 0
+ dhall-lang/tests/import/failure/unit/DontRecoverTypeError.dhall view
@@ -0,0 +1,1 @@+../../../type-inference/failure/unit/VariableFree.dhall ? 0
+ dhall-lang/tests/import/failure/unit/EnvFromRemote.dhall view
@@ -0,0 +1,13 @@+{- The following remote import attempts to import an environment variable, which+ must be disallowed by the referential sanity check++ One reason for doing this is to protect against remote imports exfiltrating+ environment variables (such as via custom headers). Only referentially+ opaque imports (i.e. local imports) have permission to refer to other+ referentially opaque imports in order to protect against this attack.++ The referential sanity check also ensures that remote imports are+ referentially transparent. Or in other words, any import that is globally+ addressable must have a meaning that is not context-sensitive.+-}+https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/data/referentiallyOpaque.dhall
+ dhall-lang/tests/import/failure/unit/FileMissing.dhall view
@@ -0,0 +1,1 @@+./not-a-file.dhall
+ dhall-lang/tests/import/failure/unit/HashMismatch.dhall view
@@ -0,0 +1,1 @@+../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ dhall-lang/tests/import/failure/unit/HashMismatch2.dhall view
@@ -0,0 +1,2 @@+-- This ensures that even if the file gets imported without hash first, the hash check is not skipped later+../../data/simple.dhall + ../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ../../data/simple.dhall
+ dhall-lang/tests/import/failure/unit/Missing.dhall view
@@ -0,0 +1,1 @@+missing
+ dhall-lang/tests/import/failure/unit/VarAcrossImportBoundary.dhall view
@@ -0,0 +1,1 @@+\(x: Bool) -> ../../data/importBoundary.dhall
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableA.dhall view
@@ -0,0 +1,1 @@+let x = 0 in (missing ? x)
+ dhall-lang/tests/import/success/unit/AlternativeWithVariableB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> x ? y
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2A.dhall view
@@ -0,0 +1,1 @@+\(x: Natural) -> (y + missing) ? x
+ dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2B.dhall view
@@ -0,0 +1,1 @@+λ(x : Natural) → x
+ dhall-lang/tests/import/success/unit/DontCacheIfHashA.dhall view
@@ -0,0 +1,5 @@+-- The let triggers a loading of `simple.dhall` in the cache,+-- but the second import uses a hash that corresponds to a different file already in the content-addressed store.+-- This test ensures that we retrieve the value corresponding to the hash and not the path even if the path is in cache.+let x = ../../data/simple.dhall+in ../../data/simple.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
+ dhall-lang/tests/import/success/unit/DontCacheIfHashB.dhall view
@@ -0,0 +1,1 @@+λ(_ : Type) → λ(_ : Optional _) → merge { `None` = True, `Some` = λ(_ : _@1) → False } _
+ dhall-lang/tests/import/success/unit/MixImportModesA.dhall view
@@ -0,0 +1,2 @@+-- This is to ensure caching doesn't accidentally confuse import modes+{ n = ../../data/simple.dhall, txt = ../../data/simple.dhall as Text, loc = ../../data/simple.dhall as Location }
+ dhall-lang/tests/import/success/unit/MixImportModesB.dhall view
@@ -0,0 +1,1 @@+{ loc = < Environment: Text | Local: Text | Missing | Remote: Text >.Local "./dhall-lang/tests/import/data/simple.dhall", n = 3, txt = "3\n" }
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureA.dhall view
@@ -0,0 +1,1 @@+../../failure/unit/FileMissing.dhall ? 0
+ dhall-lang/tests/import/success/unit/RecoverTransitiveFailureB.dhall view
@@ -0,0 +1,1 @@+0
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationA.dhall view
@@ -0,0 +1,1 @@+\(foo: { x: Bool, y: Bool }) -> \(bar: { x: Bool }) -> (foo.{x, y} // bar).{ x }
+ dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationB.dhall view
@@ -0,0 +1,3 @@+λ(foo : { x : Bool, y : Bool }) →+λ(bar : { x : Bool }) →+ (foo.{ x, y } ⫽ bar).{ x }
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall view
@@ -0,0 +1,1 @@+toMap { `if` = 0, `foo%bar` = 1 }
+ dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall view
@@ -0,0 +1,1 @@+[ { mapKey = "foo%bar", mapValue = 1 }, { mapKey = "if", mapValue = 0 } ]
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b = 1, a = 0 }
+ dhall-lang/tests/normalization/success/unit/RecordSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a = 0, b = 1 }
+ dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsA.dhall view
@@ -0,0 +1,1 @@+{ b : Bool, a : Natural }
+ dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsB.dhall view
@@ -0,0 +1,1 @@+{ a : Natural, b : Bool }
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1A.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1B.dhall view
@@ -0,0 +1,1 @@+Text/replace ""
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2A.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+ Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2B.dhall view
@@ -0,0 +1,2 @@+λ(replacement : Text) →+ Text/replace "" replacement
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3A.dhall view
@@ -0,0 +1,3 @@+λ(replacement : Text) →+λ(haystack : Text) →+ Text/replace "" replacement haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3B.dhall view
@@ -0,0 +1,1 @@+λ(replacement : Text) → λ(haystack : Text) → haystack
− dhall-lang/tests/normalization/success/unit/TextReplaceEmptyA.dhall
@@ -1,3 +0,0 @@-λ(replacement : Text) →-λ(haystack : Text) →- Text/replace "" replacement haystack
− dhall-lang/tests/normalization/success/unit/TextReplaceEmptyB.dhall
@@ -1,1 +0,0 @@-λ(replacement : Text) → λ(haystack : Text) → haystack
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingA.dhall view
@@ -0,0 +1,1 @@+Text/replace "aa" "b" "aaaaa"
+ dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingB.dhall view
@@ -0,0 +1,1 @@+"bba"
+ dhall-lang/tests/parser/success/unit/ShebangA.dhall view
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"A"
+ dhall-lang/tests/parser/success/unit/ShebangB.dhallb view
@@ -0,0 +1,1 @@+aA
+ dhall-lang/tests/parser/success/unit/ShebangNixA.dhall view
@@ -0,0 +1,3 @@+#! /usr/bin/env nix-shell+#! nix-shell -i "dhall --file" -p dhall+42
+ dhall-lang/tests/parser/success/unit/ShebangNixB.dhallb view
@@ -0,0 +1,1 @@+*
dhall-lang/tests/type-inference/success/preludeB.dhall view
@@ -319,6 +319,13 @@ ∀(cons : a → list → list) → ∀(nil : list) → list+ , foldLeft :+ ∀(a : Type) →+ ∀(xs : List a) →+ ∀(list : Type) →+ ∀(cons : list → a → list) →+ ∀(nil : list) →+ list , generate : ∀(n : Natural) → ∀(a : Type) → ∀(f : Natural → a) → List a , head : ∀(a : Type) → List a → Optional a , index : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → Optional a@@ -491,11 +498,13 @@ , concatSep : ∀(separator : Text) → ∀(elements : List Text) → Text , default : ∀(o : Optional Text) → Text , defaultMap : ∀(a : Type) → ∀(f : a → Text) → ∀(o : Optional a) → Text+ , lowerASCII : ∀(nil : Text) → Text , replace : ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text , replicate : ∀(num : Natural) → ∀(text : Text) → Text , show : Text → Text , spaces : ∀(a : Natural) → Text+ , upperASCII : ∀(nil : Text) → Text } , XML : { Type : Type
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindA.dhall view
@@ -0,0 +1,1 @@+Some ({ x = Bool } with x = 0)
+ dhall-lang/tests/type-inference/success/unit/WithInfersKindB.dhall view
@@ -0,0 +1,1 @@+Optional { x : Natural }
dhall.cabal view
@@ -1,5 +1,5 @@ Name: dhall-Version: 1.38.1+Version: 1.39.0 Cabal-Version: 2.0 Build-Type: Simple Tested-With: GHC == 8.4.3, GHC == 8.6.1@@ -496,7 +496,7 @@ hashable >= 1.2 && < 1.4 , lens-family-core >= 1.0.0 && < 2.2 , megaparsec >= 7 && < 9.1 ,- memory >= 0.14 && < 0.16,+ memory >= 0.14 && < 0.17, mmorph < 1.2 , mtl >= 2.2.1 && < 2.3 , network-uri >= 2.6 && < 2.7 ,@@ -510,7 +510,7 @@ repline >= 0.4.0.0 && < 0.5 , serialise >= 0.2.0.0 && < 0.3 , scientific >= 0.3.0.0 && < 0.4 ,- template-haskell >= 2.13.0.0 && < 2.17,+ template-haskell >= 2.13.0.0 && < 2.18, text >= 0.11.1.0 && < 1.3 , text-manipulate >= 0.2.0.1 && < 0.4 , th-lift-instances >= 0.1.13 && < 0.2 ,@@ -533,7 +533,7 @@ else Hs-Source-Dirs: ghc-src Build-Depends:- cryptonite >= 0.23 && < 1.0+ cryptonite >= 0.23 && < 0.30 if flag(with-http) Build-Depends: http-types >= 0.7.0 && < 0.13,@@ -583,6 +583,8 @@ Dhall.Import Dhall.Lint Dhall.Main+ Dhall.Marshal.Decode+ Dhall.Marshal.Encode Dhall.Map Dhall.Optics Dhall.Parser@@ -608,6 +610,7 @@ Other-Modules: Dhall.Eval Dhall.Import.Types+ Dhall.Marshal.Internal Dhall.Normalize Dhall.Parser.Combinators Dhall.Pretty.Internal@@ -667,7 +670,7 @@ either , filepath , foldl < 1.5 ,- generic-random >= 1.3.0.0 && < 1.4 ,+ generic-random >= 1.3.0.0 && < 1.5 , http-client , http-client-tls , lens-family-core ,
src/Dhall.hs view
@@ -46,2862 +46,452 @@ , detailed -- * Decoders- , Decoder (..)- , RecordDecoder(..)- , UnionDecoder(..)- , Encoder(..)- , FromDhall(..)- , Interpret- , InvalidDecoder(..)- , ExtractErrors- , ExtractError(..)- , Extractor- , MonadicExtractor- , typeError- , extractError- , toMonadic- , fromMonadic- , ExpectedTypeErrors- , ExpectedTypeError(..)- , Expector- , auto- , genericAuto- , genericAutoWith- , InterpretOptions(..)- , InputNormalizer(..)- , defaultInputNormalizer- , SingletonConstructors(..)- , defaultInterpretOptions- , bool- , natural- , integer- , word- , word8- , word16- , word32- , word64- , int- , int8- , int16- , int32- , int64- , scientific- , double- , lazyText- , strictText- , maybe- , sequence- , list- , vector- , function- , functionWith- , setFromDistinctList- , setIgnoringDuplicates- , hashSetFromDistinctList- , hashSetIgnoringDuplicates- , Dhall.map- , hashMap- , pairFromMapEntry- , unit- , void- , string- , pair- , record- , field- , union- , constructor- , GenericFromDhall(..)- , GenericFromDhallUnion(..)- , ToDhall(..)- , Inject- , inject- , genericToDhall- , genericToDhallWith- , RecordEncoder(..)- , encodeFieldWith- , encodeField- , recordEncoder- , UnionEncoder(..)- , encodeConstructorWith- , encodeConstructor- , unionEncoder- , (>|<)- , GenericToDhall(..)-- -- * Miscellaneous- , DhallErrors(..)- , showDhallErrors- , rawInput- , (>$<)- , (>*<)- , Result-- -- * Re-exports- , Natural- , Seq- , Text- , Vector- , Generic- ) where--import Control.Applicative (Alternative, empty, liftA2)-import Control.Exception (Exception)-import Control.Monad (guard)-import Control.Monad.Trans.State.Strict-import Data.Coerce (coerce)-import Data.Either.Validation- ( Validation (..)- , eitherToValidation- , validationToEither- )-import Data.Fix (Fix (..))-import Data.Functor.Contravariant (Contravariant (..), Op (..), (>$<))-import Data.Functor.Contravariant.Divisible (Divisible (..), divided)-import Data.Hashable (Hashable)-import Data.HashMap.Strict (HashMap)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Map (Map)-import Data.Scientific (Scientific)-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)-import Data.Typeable (Proxy (..), Typeable)-import Data.Vector (Vector)-import Data.Void (Void)-import Data.Word (Word8, Word16, Word32, Word64)-import Data.Int (Int8, Int16, Int32, Int64)-import Dhall.Import (Imported (..))-import Dhall.Parser (Src (..))-import Dhall.Syntax- ( Chunks (..)- , DhallDouble (..)- , Expr (..)- , FunctionBinding (..)- , RecordField (..)- , Var (..)- )-import Dhall.TypeCheck (DetailedTypeError (..), TypeError)-import GHC.Generics-import Lens.Family (LensLike', view)-import Numeric.Natural (Natural)-import Prelude hiding (maybe, sequence)-import System.FilePath (takeDirectory)--import qualified Control.Applicative-import qualified Control.Exception-import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.Foldable-import qualified Data.Functor.Compose-import qualified Data.Functor.Product-import qualified Data.HashMap.Strict as HashMap-import qualified Data.HashSet-import qualified Data.List as List-import qualified Data.List.NonEmpty-import qualified Data.Map-import qualified Data.Maybe-import qualified Data.Scientific-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text-import qualified Data.Text.IO-import qualified Data.Text.Lazy-import qualified Data.Vector-import qualified Data.Void-import qualified Dhall.Context-import qualified Dhall.Core as Core-import qualified Dhall.Import-import qualified Dhall.Map-import qualified Dhall.Parser-import qualified Dhall.Pretty.Internal-import qualified Dhall.Substitution-import qualified Dhall.TypeCheck-import qualified Dhall.Util-import qualified Lens.Family---- $setup--- >>> :set -XOverloadedStrings--- >>> :set -XRecordWildCards--- >>> import Data.Word (Word8, Word16, Word32, Word64)--- >>> import Dhall.Pretty.Internal (prettyExpr)--{-| A newtype suitable for collecting one or more errors--}-newtype DhallErrors e = DhallErrors- { getErrors :: NonEmpty e- } deriving (Eq, Functor, Semigroup)--instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)--{-| Render a given prefix and some errors to a string.--}-showDhallErrors :: Show e => String -> DhallErrors e -> String-showDhallErrors _ (DhallErrors (e :| [])) = show e-showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)- where- prefix =- "Multiple errors were encountered" ++ ctx ++ ": \n\- \ \n"--{-| Useful synonym for the `Validation` type used when marshalling Dhall- expressions--}-type Extractor s a = Validation (ExtractErrors s a)--{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall- code--}-type MonadicExtractor s a = Either (ExtractErrors s a)--{-| Generate a type error during extraction by specifying the expected type- and the actual type.- The expected type is not yet determined.--}-typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b-typeError expected actual = Failure $ case expected of- Failure e -> fmap ExpectedTypeError e- Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual---- | Turn a `Data.Text.Text` message into an extraction failure-extractError :: Text -> Extractor s a b-extractError = Failure . DhallErrors . pure . ExtractError--{-| Useful synonym for the `Validation` type used when marshalling Dhall- expressions--}-type Expector = Validation ExpectedTypeErrors--{-| One or more errors returned when determining the Dhall type of a- Haskell expression--}-type ExpectedTypeErrors = DhallErrors ExpectedTypeError--{-| Error type used when determining the Dhall type of a Haskell expression--}-data ExpectedTypeError = RecursiveTypeError- deriving (Eq, Show)--instance Exception ExpectedTypeError--instance Show ExpectedTypeErrors where- show = showDhallErrors " while determining the expected type"---- | Switches from an @Applicative@ extraction result, able to accumulate errors,--- to a @Monad@ extraction result, able to chain sequential operations-toMonadic :: Extractor s a b -> MonadicExtractor s a b-toMonadic = validationToEither---- | Switches from a @Monad@ extraction result, able to chain sequential errors,--- to an @Applicative@ extraction result, able to accumulate errors-fromMonadic :: MonadicExtractor s a b -> Extractor s a b-fromMonadic = eitherToValidation--{-| One or more errors returned from extracting a Dhall expression to a- Haskell expression--}-type ExtractErrors s a = DhallErrors (ExtractError s a)--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where- show = showDhallErrors " during extraction"--{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,- as expressions are type-checked against the expected type before being passed to @extract@), or- a term-level error, described with a freeform text value.--}-data ExtractError s a =- TypeMismatch (InvalidDecoder s a)- | ExpectedTypeError ExpectedTypeError- | ExtractError Text--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where- show (TypeMismatch e) = show e- show (ExpectedTypeError e) = show e- show (ExtractError es) =- _ERROR <> ": Failed extraction \n\- \ \n\- \The expression type-checked successfully but the transformation to the target \n\- \type failed with the following error: \n\- \ \n\- \" <> Data.Text.unpack es <> "\n\- \ \n"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)--{-| Every `Decoder` must obey the contract that if an expression's type matches- the `expected` type then the `extract` function must not fail with a type- error. However, decoding may still fail for other reasons (such as the- decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate- elements).-- This error type is used to indicate an internal error in the implementation- of a `Decoder` where the expected type matched the Dhall expression, but the- expression supplied to the extraction function did not match the expected- type. If this happens that means that the `Decoder` itself needs to be- fixed.--}-data InvalidDecoder s a = InvalidDecoder- { invalidDecoderExpected :: Expr s a- , invalidDecoderExpression :: Expr s a- }- deriving (Typeable)--instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where- show InvalidDecoder { .. } =- _ERROR <> ": Invalid Dhall.Decoder \n\- \ \n\- \Every Decoder must provide an extract function that does not fail with a type \n\- \error if an expression matches the expected type. You provided a Decoder that \n\- \disobeys this contract \n\- \ \n\- \The Decoder provided has the expected dhall type: \n\- \ \n\- \" <> show txt0 <> "\n\- \ \n\- \and it threw a type error during extraction from the well-typed expression: \n\- \ \n\- \" <> show txt1 <> "\n\- \ \n"- where- txt0 = Dhall.Util.insert invalidDecoderExpected- txt1 = Dhall.Util.insert invalidDecoderExpression---- | @since 1.16-data InputSettings = InputSettings- { _rootDirectory :: FilePath- , _sourceName :: FilePath- , _evaluateSettings :: EvaluateSettings- }---- | Default input settings: resolves imports relative to @.@ (the--- current working directory), report errors as coming from @(input)@,--- and default evaluation settings from 'defaultEvaluateSettings'.------ @since 1.16-defaultInputSettings :: InputSettings-defaultInputSettings = InputSettings- { _rootDirectory = "."- , _sourceName = "(input)"- , _evaluateSettings = defaultEvaluateSettings- }----- | Access the directory to resolve imports relative to.------ @since 1.16-rootDirectory- :: (Functor f)- => LensLike' f InputSettings FilePath-rootDirectory k s =- fmap (\x -> s { _rootDirectory = x }) (k (_rootDirectory s))---- | Access the name of the source to report locations from; this is--- only used in error messages, so it's okay if this is a best guess--- or something symbolic.------ @since 1.16-sourceName- :: (Functor f)- => LensLike' f InputSettings FilePath-sourceName k s =- fmap (\x -> s { _sourceName = x}) (k (_sourceName s))---- | @since 1.16-data EvaluateSettings = EvaluateSettings- { _substitutions :: Dhall.Substitution.Substitutions Src Void- , _startingContext :: Dhall.Context.Context (Expr Src Void)- , _normalizer :: Maybe (Core.ReifiedNormalizer Void)- , _newManager :: IO Dhall.Import.Manager- }---- | Default evaluation settings: no extra entries in the initial--- context, and no special normalizer behaviour.------ @since 1.16-defaultEvaluateSettings :: EvaluateSettings-defaultEvaluateSettings = EvaluateSettings- { _substitutions = Dhall.Substitution.empty- , _startingContext = Dhall.Context.empty- , _normalizer = Nothing- , _newManager = Dhall.Import.defaultNewManager- }---- | Access the starting context used for evaluation and type-checking.------ @since 1.16-startingContext- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Dhall.Context.Context (Expr Src Void))-startingContext = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Dhall.Context.Context (Expr Src Void))- l k s = fmap (\x -> s { _startingContext = x}) (k (_startingContext s))---- | Access the custom substitutions.------ @since 1.30-substitutions- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Dhall.Substitution.Substitutions Src Void)-substitutions = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Dhall.Substitution.Substitutions Src Void)- l k s = fmap (\x -> s { _substitutions = x }) (k (_substitutions s))---- | Access the custom normalizer.------ @since 1.16-normalizer- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Maybe (Core.ReifiedNormalizer Void))-normalizer = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Maybe (Core.ReifiedNormalizer Void))- l k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s))---- | Access the HTTP manager initializer.------ @since 1.36-newManager- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (IO Dhall.Import.Manager)-newManager = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (IO Dhall.Import.Manager)- l k s = fmap (\x -> s { _newManager = x }) (k (_newManager s))---- | @since 1.16-class HasEvaluateSettings s where- evaluateSettings- :: (Functor f)- => LensLike' f s EvaluateSettings--instance HasEvaluateSettings InputSettings where- evaluateSettings k s =- fmap (\x -> s { _evaluateSettings = x }) (k (_evaluateSettings s))--instance HasEvaluateSettings EvaluateSettings where- evaluateSettings = id--{-| Type-check and evaluate a Dhall program, decoding the result into Haskell-- The first argument determines the type of value that you decode:-->>> input integer "+2"-2->>> input (vector double) "[1.0, 2.0]"-[1.0,2.0]-- Use `auto` to automatically select which type to decode based on the- inferred return type:-->>> input auto "True" :: IO Bool-True-- This uses the settings from 'defaultInputSettings'.--}-input- :: Decoder a- -- ^ The decoder for the Dhall value- -> Text- -- ^ The Dhall program- -> IO a- -- ^ The decoded value in Haskell-input =- inputWithSettings defaultInputSettings--{-| Extend 'input' with a root directory to resolve imports relative- to, a file to mention in errors as the source, a custom typing- context, and a custom normalization process.--@since 1.16--}-inputWithSettings- :: InputSettings- -> Decoder a- -- ^ The decoder for the Dhall value- -> Text- -- ^ The Dhall program- -> IO a- -- ^ The decoded value in Haskell-inputWithSettings settings (Decoder {..}) txt = do- expected' <- case expected of- Success x -> return x- Failure e -> Control.Exception.throwIO e-- let suffix = Dhall.Pretty.Internal.prettyToStrictText expected'- let annotate substituted = case substituted of- Note (Src begin end bytes) _ ->- Note (Src begin end bytes') (Annot substituted expected')- where- bytes' = bytes <> " : " <> suffix- _ ->- Annot substituted expected'-- normExpr <- inputHelper annotate settings txt-- case extract normExpr of- Success x -> return x- Failure e -> Control.Exception.throwIO e--{-| Type-check and evaluate a Dhall program that is read from the- file-system.-- This uses the settings from 'defaultEvaluateSettings'.-- @since 1.16--}-inputFile- :: Decoder a- -- ^ The decoder for the Dhall value- -> FilePath- -- ^ The path to the Dhall program.- -> IO a- -- ^ The decoded value in Haskell.-inputFile =- inputFileWithSettings defaultEvaluateSettings--{-| Extend 'inputFile' with a custom typing context and a custom- normalization process.--@since 1.16--}-inputFileWithSettings- :: EvaluateSettings- -> Decoder a- -- ^ The decoder for the Dhall value- -> FilePath- -- ^ The path to the Dhall program.- -> IO a- -- ^ The decoded value in Haskell.-inputFileWithSettings settings ty path = do- text <- Data.Text.IO.readFile path- let inputSettings = InputSettings- { _rootDirectory = takeDirectory path- , _sourceName = path- , _evaluateSettings = settings- }- inputWithSettings inputSettings ty text--{-| Similar to `input`, but without interpreting the Dhall `Expr` into a Haskell- type.-- Uses the settings from 'defaultInputSettings'.--}-inputExpr- :: Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputExpr =- inputExprWithSettings defaultInputSettings--{-| Extend 'inputExpr' with a root directory to resolve imports relative- to, a file to mention in errors as the source, a custom typing- context, and a custom normalization process.--@since 1.16--}-inputExprWithSettings- :: InputSettings- -> Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputExprWithSettings = inputHelper id--{-| Helper function for the input* function family--@since 1.30--}-inputHelper- :: (Expr Src Void -> Expr Src Void)- -> InputSettings- -> Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputHelper annotate settings txt = do- expr <- Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)-- let InputSettings {..} = settings-- let EvaluateSettings {..} = _evaluateSettings-- let transform =- Lens.Family.set Dhall.Import.substitutions _substitutions- . Lens.Family.set Dhall.Import.normalizer _normalizer- . Lens.Family.set Dhall.Import.startingContext _startingContext-- let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)-- expr' <- State.evalStateT (Dhall.Import.loadWith expr) status-- let substituted = Dhall.Substitution.substitute expr' $ view substitutions settings- let annot = annotate substituted- _ <- Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot)- pure (Core.normalizeWith (view normalizer settings) substituted)---- | Use this function to extract Haskell values directly from Dhall AST.--- The intended use case is to allow easy extraction of Dhall values for--- making the function `Core.normalizeWith` easier to use.------ For other use cases, use `input` from "Dhall" module. It will give you--- a much better user experience.-rawInput- :: Alternative f- => Decoder a- -- ^ The decoder for the Dhall value- -> Expr s Void- -- ^ a closed form Dhall program, which evaluates to the expected type- -> f a- -- ^ The decoded value in Haskell-rawInput (Decoder {..}) expr =- case extract (Core.normalize expr) of- Success x -> pure x- Failure _e -> empty--{-| Use this to provide more detailed error messages-->> input auto "True" :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> True : Integer->-> (input):1:1-->> detailed (input auto "True") :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> Explanation: You can annotate an expression with its type or kind using the-> ❰:❱ symbol, like this:->->-> ┌───────┐-> │ x : t │ ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱-> └───────┘->-> The type checker verifies that the expression's type or kind matches the-> provided annotation->-> For example, all of the following are valid annotations that the type checker-> accepts:->->-> ┌─────────────┐-> │ 1 : Natural │ ❰1❱ is an expression that has type ❰Natural❱, so the type-> └─────────────┘ checker accepts the annotation->->-> ┌───────────────────────┐-> │ Natural/even 2 : Bool │ ❰Natural/even 2❱ has type ❰Bool❱, so the type-> └───────────────────────┘ checker accepts the annotation->->-> ┌────────────────────┐-> │ List : Type → Type │ ❰List❱ is an expression that has kind ❰Type → Type❱,-> └────────────────────┘ so the type checker accepts the annotation->->-> ┌──────────────────┐-> │ List Text : Type │ ❰List Text❱ is an expression that has kind ❰Type❱, so-> └──────────────────┘ the type checker accepts the annotation->->-> However, the following annotations are not valid and the type checker will-> reject them:->->-> ┌──────────┐-> │ 1 : Text │ The type checker rejects this because ❰1❱ does not have type-> └──────────┘ ❰Text❱->->-> ┌─────────────┐-> │ List : Type │ ❰List❱ does not have kind ❰Type❱-> └─────────────┘->->-> You or the interpreter annotated this expression:->-> ↳ True->-> ... with this type or kind:->-> ↳ Integer->-> ... but the inferred type or kind of the expression is actually:->-> ↳ Bool->-> Some common reasons why you might get this error:->-> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation-> matching the expected type->-> For example, if you run the following Haskell code:->->-> ┌───────────────────────────────┐-> │ >>> input auto "1" :: IO Text │-> └───────────────────────────────┘->->-> ... then the interpreter will actually type check the following annotated-> expression:->->-> ┌──────────┐-> │ 1 : Text │-> └──────────┘->->-> ... and then type-checking will fail->-> ────────────────────────────────────────────────────────────────────────────────->-> True : Integer->-> (input):1:1---}-detailed :: IO a -> IO a-detailed =- Control.Exception.handle handler1 . Control.Exception.handle handler0- where- handler0 :: Imported (TypeError Src Void) -> IO a- handler0 (Imported ps e) =- Control.Exception.throwIO (Imported ps (DetailedTypeError e))-- handler1 :: TypeError Src Void -> IO a- handler1 e = Control.Exception.throwIO (DetailedTypeError e)--{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall- into Haskell-- You can produce `Decoder`s either explicitly:--> example :: Decoder (Vector Text)-> example = vector text-- ... or implicitly using `auto`:--> example :: Decoder (Vector Text)-> example = auto-- You can consume `Decoder`s using the `input` function:--> input :: Decoder a -> Text -> IO a--}-data Decoder a = Decoder- { extract :: Expr Src Void -> Extractor Src Void a- -- ^ Extracts Haskell value from the Dhall expression- , expected :: Expector (Expr Src Void)- -- ^ Dhall type of the Haskell value- }- deriving (Functor)--{-| Decode a `Prelude.Bool`-->>> input bool "True"-True--}-bool :: Decoder Bool-bool = Decoder {..}- where- extract (BoolLit b) = pure b- extract expr = typeError expected expr-- expected = pure Bool--{-| Decode a `Prelude.Natural`-->>> input natural "42"-42--}-natural :: Decoder Natural-natural = Decoder {..}- where- extract (NaturalLit n) = pure n- extract expr = typeError expected expr-- expected = pure Natural--{-| Decode an `Prelude.Integer`-->>> input integer "+42"-42--}-integer :: Decoder Integer-integer = Decoder {..}- where- extract (IntegerLit n) = pure n- extract expr = typeError expected expr-- expected = pure Integer--wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a-wordHelper name = Decoder {..}- where- extract (NaturalLit n)- | toInteger n <= toInteger (maxBound @a) =- pure (fromIntegral n)- | otherwise =- extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))- extract expr =- typeError expected expr-- expected = pure Natural--{-| Decode a `Word` from a Dhall @Natural@-->>> input word "42"-42--}-word :: Decoder Word-word = wordHelper "Word"--{-| Decode a `Word8` from a Dhall @Natural@-->>> input word8 "42"-42--}-word8 :: Decoder Word8-word8 = wordHelper "Word8"--{-| Decode a `Word16` from a Dhall @Natural@-->>> input word16 "42"-42--}-word16 :: Decoder Word16-word16 = wordHelper "Word16"--{-| Decode a `Word32` from a Dhall @Natural@-->>> input word32 "42"-42--}-word32 :: Decoder Word32-word32 = wordHelper "Word32"--{-| Decode a `Word64` from a Dhall @Natural@-->>> input word64 "42"-42--}-word64 :: Decoder Word64-word64 = wordHelper "Word64"--intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a-intHelper name = Decoder {..}- where- extract (IntegerLit n)- | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =- pure (fromIntegral n)- | otherwise =- extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))- extract expr =- typeError expected expr-- expected = pure Integer--{-| Decode an `Int` from a Dhall @Integer@-->>> input int "-42"--42--}-int :: Decoder Int-int = intHelper "Int"--{-| Decode an `Int8` from a Dhall @Integer@-->>> input int8 "-42"--42--}-int8 :: Decoder Int8-int8 = intHelper "Int8"--{-| Decode an `Int16` from a Dhall @Integer@-->>> input int16 "-42"--42--}-int16 :: Decoder Int16-int16 = intHelper "Int16"--{-| Decode an `Int32` from a Dhall @Integer@-->>> input int32 "-42"--42--}-int32 :: Decoder Int32-int32 = intHelper "Int32"--{-| Decode an `Int64` from a Dhall @Integer@-->>> input int64 "-42"--42--}-int64 :: Decoder Int64-int64 = intHelper "Int64"--{-| Decode a `Scientific`-r-->>> input scientific "1e100"-1.0e100--}-scientific :: Decoder Scientific-scientific = fmap Data.Scientific.fromFloatDigits double--{-| Decode a `Prelude.Double`-->>> input double "42.0"-42.0--}-double :: Decoder Double-double = Decoder {..}- where- extract (DoubleLit (DhallDouble n)) = pure n- extract expr = typeError expected expr-- expected = pure Double--{-| Decode lazy `Data.Text.Text`-->>> input lazyText "\"Test\""-"Test"--}-lazyText :: Decoder Data.Text.Lazy.Text-lazyText = fmap Data.Text.Lazy.fromStrict strictText--{-| Decode strict `Data.Text.Text`-->>> input strictText "\"Test\""-"Test"--}-strictText :: Decoder Text-strictText = Decoder {..}- where- extract (TextLit (Chunks [] t)) = pure t- extract expr = typeError expected expr-- expected = pure Text--{-| Decode a `Maybe`-->>> input (maybe natural) "Some 1"-Just 1--}-maybe :: Decoder a -> Decoder (Maybe a)-maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (Some e ) = fmap Just (extractIn e)- extractOut (App None _) = pure Nothing- extractOut expr = typeError expectedOut expr-- expectedOut = App Optional <$> expectedIn--{-| Decode a `Seq`-->>> input (sequence natural) "[1, 2, 3]"-fromList [1,2,3]--}-sequence :: Decoder a -> Decoder (Seq a)-sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (ListLit _ es) = traverse extractIn es- extractOut expr = typeError expectedOut expr-- expectedOut = App List <$> expectedIn--{-| Decode a list-->>> input (list natural) "[1, 2, 3]"-[1,2,3]--}-list :: Decoder a -> Decoder [a]-list = fmap Data.Foldable.toList . sequence--{-| Decode a `Vector`-->>> input (vector natural) "[1, 2, 3]"-[1,2,3]--}-vector :: Decoder a -> Decoder (Vector a)-vector = fmap Data.Vector.fromList . list--{-| Decode a Dhall function into a Haskell function-->>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)->>> f 0-True->>> f 1-False--}-function- :: Encoder a- -> Decoder b- -> Decoder (a -> b)-function = functionWith defaultInputNormalizer--{-| Decode a Dhall function into a Haskell function using the specified normalizer-->>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)->>> f 0-True->>> f 1-False--}-functionWith- :: InputNormalizer- -> Encoder a- -> Decoder b- -> Decoder (a -> b)-functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =- Decoder extractOut expectedOut- where- normalizer_ = Just (getInputNormalizer inputNormalizer)-- extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of- Success o -> o- Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )-- expectedOut = Pi mempty "_" declared <$> expectedIn--{-| Decode a `Data.Set.Set` from a `List`-->>> input (setIgnoringDuplicates natural) "[1, 2, 3]"-fromList [1,2,3]--Duplicate elements are ignored.-->>> input (setIgnoringDuplicates natural) "[1, 1, 3]"-fromList [1,3]---}-setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)-setIgnoringDuplicates = fmap Data.Set.fromList . list--{-| Decode a `Data.HashSet.HashSet` from a `List`-->>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"-fromList [1,2,3]--Duplicate elements are ignored.-->>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"-fromList [1,3]---}-hashSetIgnoringDuplicates :: (Hashable a, Ord a)- => Decoder a- -> Decoder (Data.HashSet.HashSet a)-hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list--{-| Decode a `Data.Set.Set` from a `List` with distinct elements-->>> input (setFromDistinctList natural) "[1, 2, 3]"-fromList [1,2,3]--An error is thrown if the list contains duplicates.--> >>> input (setFromDistinctList natural) "[1, 1, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> One duplicate element in the list: 1->--> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> 2 duplicates were found in the list, including 1->---}-setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)-setFromDistinctList = setHelper Data.Set.size Data.Set.fromList--{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements-->>> input (hashSetFromDistinctList natural) "[1, 2, 3]"-fromList [1,2,3]--An error is thrown if the list contains duplicates.--> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> One duplicate element in the list: 1->--> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> 2 duplicates were found in the list, including 1->---}-hashSetFromDistinctList :: (Hashable a, Ord a, Show a)- => Decoder a- -> Decoder (Data.HashSet.HashSet a)-hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList---setHelper :: (Eq a, Foldable t, Show a)- => (t a -> Int)- -> ([a] -> t a)- -> Decoder a- -> Decoder (t a)-setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (ListLit _ es) = case traverse extractIn es of- Success vSeq- | sameSize -> Success vSet- | otherwise -> extractError err- where- vList = Data.Foldable.toList vSeq- vSet = toSet vList- sameSize = size vSet == Data.Sequence.length vSeq- duplicates = vList List.\\ Data.Foldable.toList vSet- err | length duplicates == 1 =- "One duplicate element in the list: "- <> (Data.Text.pack $ show $ head duplicates)- | otherwise = Data.Text.pack $ unwords- [ show $ length duplicates- , "duplicates were found in the list, including"- , show $ head duplicates- ]- Failure f -> Failure f- extractOut expr = typeError expectedOut expr-- expectedOut = App List <$> expectedIn--{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@-->>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"-fromList [("a",True),("b",False)]->>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"-fromList [("foo",True)]--If there are duplicate @mapKey@s, later @mapValue@s take precedence:-->>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"->>> input (Dhall.map natural bool) expr-fromList [(1,False)]---}-map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)-map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))--{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@-->>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }")-[("a",True),("b",False)]->>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]")-[("foo",True)]--If there are duplicate @mapKey@s, later @mapValue@s take precedence:-->>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"->>> input (Dhall.hashMap natural bool) expr-fromList [(1,False)]---}-hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)-hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))--{-| Decode a tuple from a @Prelude.Map.Entry@ record-->>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"-("foo",3)--}-pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)-pairFromMapEntry k v = Decoder extractOut expectedOut- where- extractOut (RecordLit kvs)- | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs- , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs- = liftA2 (,) (extract k key) (extract v value)- extractOut expr = typeError expectedOut expr-- expectedOut = do- k' <- Core.makeRecordField <$> expected k- v' <- Core.makeRecordField <$> expected v- pure $ Record $ Dhall.Map.fromList- [ ("mapKey", k')- , ("mapValue", v')]--{-| Decode @()@ from an empty record.-->>> input unit "{=}" -- GHC doesn't print the result if it is ()---}-unit :: Decoder ()-unit = Decoder {..}- where- extract (RecordLit fields)- | Data.Foldable.null fields = pure ()- extract expr = typeError expected expr-- expected = pure $ Record mempty--{-| Decode 'Void' from an empty union.--Since @<>@ is uninhabited, @'input' 'void'@ will always fail.--}-void :: Decoder Void-void = union mempty--{-| Decode a `String`-->>> input string "\"ABC\""-"ABC"---}-string :: Decoder String-string = Data.Text.Lazy.unpack <$> lazyText--{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.-->>> input (pair natural bool) "{ _1 = 42, _2 = False }"-(42,False)--}-pair :: Decoder a -> Decoder b -> Decoder (a, b)-pair l r = Decoder extractOut expectedOut- where- extractOut expr@(RecordLit fields) =- (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)- (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)- <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)- (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)- extractOut expr = typeError expectedOut expr-- expectedOut = do- l' <- Core.makeRecordField <$> expected l- r' <- Core.makeRecordField <$> expected r- pure $ Record $ Dhall.Map.fromList- [ ("_1", l')- , ("_2", r')]--{-| Any value that implements `FromDhall` can be automatically decoded based on- the inferred return type of `input`-->>> input auto "[1, 2, 3]" :: IO (Vector Natural)-[1,2,3]->>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)-fromList [("a",False),("b",True)]-- This class auto-generates a default implementation for types that- implement `Generic`. This does not auto-generate an instance for recursive- types.-- The default instance can be tweaked using 'genericAutoWith' and custom- 'InterpretOptions', or using- [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)- and 'Dhall.Deriving.Codec' from "Dhall.Deriving".--}-class FromDhall a where- autoWith :: InputNormalizer -> Decoder a- default autoWith- :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a- autoWith _ = genericAuto---- | A compatibility alias for `FromDhall`-type Interpret = FromDhall-{-# DEPRECATED Interpret "Use FromDhall instead" #-}--instance FromDhall Void where- autoWith _ = void--instance FromDhall () where- autoWith _ = unit--instance FromDhall Bool where- autoWith _ = bool--instance FromDhall Natural where- autoWith _ = natural--instance FromDhall Word where- autoWith _ = word--instance FromDhall Word8 where- autoWith _ = word8--instance FromDhall Word16 where- autoWith _ = word16--instance FromDhall Word32 where- autoWith _ = word32--instance FromDhall Word64 where- autoWith _ = word64--instance FromDhall Integer where- autoWith _ = integer--instance FromDhall Int where- autoWith _ = int--instance FromDhall Int8 where- autoWith _ = int8--instance FromDhall Int16 where- autoWith _ = int16--instance FromDhall Int32 where- autoWith _ = int32--instance FromDhall Int64 where- autoWith _ = int64--instance FromDhall Scientific where- autoWith _ = scientific--instance FromDhall Double where- autoWith _ = double--instance {-# OVERLAPS #-} FromDhall [Char] where- autoWith _ = string--instance FromDhall Data.Text.Lazy.Text where- autoWith _ = lazyText--instance FromDhall Text where- autoWith _ = strictText--instance FromDhall a => FromDhall (Maybe a) where- autoWith opts = maybe (autoWith opts)--instance FromDhall a => FromDhall (Seq a) where- autoWith opts = sequence (autoWith opts)--instance FromDhall a => FromDhall [a] where- autoWith opts = list (autoWith opts)--instance FromDhall a => FromDhall (Vector a) where- autoWith opts = vector (autoWith opts)--{-| Note that this instance will throw errors in the presence of duplicates in- the list. To ignore duplicates, use `setIgnoringDuplicates`.--}-instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where- autoWith opts = setFromDistinctList (autoWith opts)--{-| Note that this instance will throw errors in the presence of duplicates in- the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.--}-instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where- autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)--instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where- autoWith inputNormalizer = Dhall.map (autoWith inputNormalizer) (autoWith inputNormalizer)--instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where- autoWith inputNormalizer = Dhall.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)--instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where- autoWith inputNormalizer =- functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)--instance (FromDhall a, FromDhall b) => FromDhall (a, b)--{-| Use the default input normalizer for interpreting a configuration file--> auto = autoWith defaultInputNormalizer--}-auto :: FromDhall a => Decoder a-auto = autoWith defaultInputNormalizer--{-| This type is exactly the same as `Data.Fix.Fix` except with a different- `FromDhall` instance. This intermediate type simplifies the implementation- of the inner loop for the `FromDhall` instance for `Fix`--}-newtype Result f = Result { _unResult :: f (Result f) }--resultToFix :: Functor f => Result f -> Fix f-resultToFix (Result x) = Fix (fmap resultToFix x)--fixToResult :: Functor f => Fix f -> Result f-fixToResult (Fix x) = Result (fmap fixToResult x)--instance FromDhall (f (Result f)) => FromDhall (Result f) where- autoWith inputNormalizer = Decoder {..}- where- extract (App _ expr) =- fmap Result (Dhall.extract (autoWith inputNormalizer) expr)- extract expr = typeError expected expr-- expected = pure "result"--instance ToDhall (f (Result f)) => ToDhall (Result f) where- injectWith inputNormalizer = Encoder {..}- where- embed = App "Make" . Dhall.embed (injectWith inputNormalizer) . _unResult- declared = "result"---- | You can use this instance to marshal recursive types from Dhall to Haskell.------ Here is an example use of this instance:------ > {-# LANGUAGE DeriveAnyClass #-}--- > {-# LANGUAGE DeriveFoldable #-}--- > {-# LANGUAGE DeriveFunctor #-}--- > {-# LANGUAGE DeriveTraversable #-}--- > {-# LANGUAGE DeriveGeneric #-}--- > {-# LANGUAGE KindSignatures #-}--- > {-# LANGUAGE QuasiQuotes #-}--- > {-# LANGUAGE StandaloneDeriving #-}--- > {-# LANGUAGE TypeFamilies #-}--- > {-# LANGUAGE TemplateHaskell #-}--- >--- > import Data.Fix (Fix(..))--- > import Data.Text (Text)--- > import Dhall (FromDhall)--- > import GHC.Generics (Generic)--- > import Numeric.Natural (Natural)--- >--- > import qualified Data.Fix as Fix--- > import qualified Data.Functor.Foldable as Foldable--- > import qualified Data.Functor.Foldable.TH as TH--- > import qualified Dhall--- > import qualified NeatInterpolation--- >--- > data Expr--- > = Lit Natural--- > | Add Expr Expr--- > | Mul Expr Expr--- > deriving (Show)--- >--- > TH.makeBaseFunctor ''Expr--- >--- > deriving instance Generic (ExprF a)--- > deriving instance FromDhall a => FromDhall (ExprF a)--- >--- > example :: Text--- > example = [NeatInterpolation.text|--- > \(Expr : Type)--- > -> let ExprF =--- > < LitF :--- > Natural--- > | AddF :--- > { _1 : Expr, _2 : Expr }--- > | MulF :--- > { _1 : Expr, _2 : Expr }--- > >--- >--- > in \(Fix : ExprF -> Expr)--- > -> let Lit = \(x : Natural) -> Fix (ExprF.LitF x)--- >--- > let Add =--- > \(x : Expr)--- > -> \(y : Expr)--- > -> Fix (ExprF.AddF { _1 = x, _2 = y })--- >--- > let Mul =--- > \(x : Expr)--- > -> \(y : Expr)--- > -> Fix (ExprF.MulF { _1 = x, _2 = y })--- >--- > in Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))--- > |]--- >--- > convert :: Fix ExprF -> Expr--- > convert = Fix.foldFix Foldable.embed--- >--- > main :: IO ()--- > main = do--- > x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)--- >--- > print (convert x :: Expr)-instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where- autoWith inputNormalizer = Decoder {..}- where- extract expr0 = extract0 expr0- where- die = typeError expected expr0-- extract0 (Lam _ (FunctionBinding { functionBindingVariable = x }) expr) =- extract1 (rename x "result" expr)- extract0 _ = die-- extract1 (Lam _ (FunctionBinding { functionBindingVariable = y }) expr) =- extract2 (rename y "Make" expr)- extract1 _ = die-- extract2 expr = fmap resultToFix (Dhall.extract (autoWith inputNormalizer) expr)-- rename a b expr- | a /= b = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)- | otherwise = expr-- expected = (\x -> Pi mempty "result" (Const Core.Type) (Pi mempty "Make" (Pi mempty "_" x "result") "result"))- <$> Dhall.expected (autoWith inputNormalizer :: Decoder (f (Result f)))--instance forall f. (Functor f, ToDhall (f (Result f))) => ToDhall (Fix f) where- injectWith inputNormalizer = Encoder {..}- where- embed fixf =- Lam Nothing (Core.makeFunctionBinding "result" (Const Core.Type)) $- Lam Nothing (Core.makeFunctionBinding "Make" makeType) $- embed' . fixToResult $ fixf-- declared = Pi Nothing "result" (Const Core.Type) $ Pi Nothing "_" makeType "result"-- makeType = Pi Nothing "_" declared' "result"- Encoder embed' _ = injectWith @(Dhall.Result f) inputNormalizer- Encoder _ declared' = injectWith @(f (Dhall.Result f)) inputNormalizer--{-| `genericAuto` is the default implementation for `auto` if you derive- `FromDhall`. The difference is that you can use `genericAuto` without- having to explicitly provide a `FromDhall` instance for a type as long as- the type derives `Generic`--}-genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a-genericAuto = genericAutoWith defaultInterpretOptions--{-| `genericAutoWith` is a configurable version of `genericAuto`.--}-genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a-genericAutoWith options = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p defaultInputNormalizer options) 1))- where- withProxy :: (Proxy a -> Decoder a) -> Decoder a- withProxy f = f Proxy---{-| Use these options to tweak how Dhall derives a generic implementation of- `FromDhall`--}-data InterpretOptions = InterpretOptions- { fieldModifier :: Text -> Text- -- ^ Function used to transform Haskell field names into their corresponding- -- Dhall field names- , constructorModifier :: Text -> Text- -- ^ Function used to transform Haskell constructor names into their- -- corresponding Dhall alternative names- , singletonConstructors :: SingletonConstructors- -- ^ Specify how to handle constructors with only one field. The default is- -- `Smart`- }---- | This is only used by the `FromDhall` instance for functions in order--- to normalize the function input before marshaling the input into a--- Dhall expression-newtype InputNormalizer = InputNormalizer- { getInputNormalizer :: Core.ReifiedNormalizer Void }---- | Default normalization-related settings (no custom normalization)-defaultInputNormalizer :: InputNormalizer-defaultInputNormalizer = InputNormalizer- { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }--{-| This type specifies how to model a Haskell constructor with 1 field in- Dhall-- For example, consider the following Haskell datatype definition:-- > data Example = Foo { x :: Double } | Bar Double-- Depending on which option you pick, the corresponding Dhall type could be:-- > < Foo : Double | Bar : Double > -- Bare-- > < Foo : { x : Double } | Bar : { _1 : Double } > -- Wrapped-- > < Foo : { x : Double } | Bar : Double > -- Smart--}-data SingletonConstructors- = Bare- -- ^ Never wrap the field in a record- | Wrapped- -- ^ Always wrap the field in a record- | Smart- -- ^ Only fields in a record if they are named--{-| Default interpret options for generics-based instances,- which you can tweak or override, like this:--> genericAutoWith-> (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })--}-defaultInterpretOptions :: InterpretOptions-defaultInterpretOptions = InterpretOptions- { fieldModifier =- id- , constructorModifier =- id- , singletonConstructors =- Smart- }--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation--}-class GenericFromDhall t f where- genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))--instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where- genericAutoWithNormalizer p inputNormalizer options = do- res <- genericAutoWithNormalizer p inputNormalizer options- pure (fmap M1 res)--instance GenericFromDhall t V1 where- genericAutoWithNormalizer _ _ _ = pure Decoder {..}- where- extract expr = typeError expected expr-- expected = pure $ Union mempty--unsafeExpectUnion- :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))-unsafeExpectUnion _ (Union kts) =- kts-unsafeExpectUnion name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectRecord- :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)-unsafeExpectRecord _ (Record kts) =- kts-unsafeExpectRecord name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectUnionLit- :: Text- -> Expr Src Void- -> (Text, Maybe (Expr Src Void))-unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =- (k, Nothing)-unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =- (k, Just v)-unsafeExpectUnionLit name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectRecordLit- :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)-unsafeExpectRecordLit _ (RecordLit kvs) =- kvs-unsafeExpectRecordLit name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)-notEmptyRecordLit e = case e of- RecordLit m | null m -> Nothing- _ -> Just e--notEmptyRecord :: Expr s a -> Maybe (Expr s a)-notEmptyRecord e = case e of- Record m | null m -> Nothing- _ -> Just e-extractUnionConstructor- :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))-extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =- return (fld, e, Dhall.Map.delete fld kts)-extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =- return (fld, RecordLit mempty, Dhall.Map.delete fld kts)-extractUnionConstructor _ =- empty--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation for a union type--}-class GenericFromDhallUnion t f where- genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)--instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where- genericUnionAutoWithNormalizer p inputNormalizer options =- (<>)- (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)- (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)--instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where- genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =- constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)- where- n :: M1 C c1 f1 a- n = undefined-- name = constructorModifier (Data.Text.pack (conName n))--instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where- genericAutoWithNormalizer p inputNormalizer options =- pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))--instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where- genericAutoWithNormalizer p inputNormalizer options = do- res <- genericAutoWithNormalizer p inputNormalizer options- pure (fmap M1 res)--instance GenericFromDhall t U1 where- genericAutoWithNormalizer _ _ _ = pure (Decoder {..})- where- extract _ = pure U1-- expected = pure expected'-- expected' = Record (Dhall.Map.fromList [])--getSelName :: Selector s => M1 i s f a -> State Int Text-getSelName n = case selName n of- "" -> do i <- get- put (i + 1)- pure (Data.Text.pack ("_" ++ show i))- nn -> pure (Data.Text.pack nn)--instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where- genericAutoWithNormalizer p inputNormalizer options = do- Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options- Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options-- let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL- let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR-- let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)-- let extract expression =- liftA2 (:*:) (extractL expression) (extractR expression)-- return (Decoder {..})--instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where- genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do- let nR :: M1 S s (K1 i a) r- nR = undefined-- nameR <- fmap fieldModifier (getSelName nR)-- Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options-- let Decoder extractR expectedR = autoWith inputNormalizer-- let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL-- let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of- Just expressionR ->- liftA2 (:*:)- (extractL expression)- (fmap (M1 . K1) (extractR expressionR))- _ -> die- _ -> die-- return (Decoder {..})--instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where- genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do- let nL :: M1 S s (K1 i a) r- nL = undefined-- nameL <- fmap fieldModifier (getSelName nL)-- let Decoder extractL expectedL = autoWith inputNormalizer-- Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options-- let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR-- let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of- Just expressionL ->- liftA2 (:*:)- (fmap (M1 . K1) (extractL expressionL))- (extractR expression)- _ -> die- _ -> die-- return (Decoder {..})--instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do- let nL :: M1 S s1 (K1 i1 a1) r- nL = undefined-- let nR :: M1 S s2 (K1 i2 a2) r- nR = undefined-- nameL <- fmap fieldModifier (getSelName nL)- nameR <- fmap fieldModifier (getSelName nR)-- let Decoder extractL expectedL = autoWith inputNormalizer- let Decoder extractR expectedR = autoWith inputNormalizer-- let expected = do- l <- Core.makeRecordField <$> expectedL- r <- Core.makeRecordField <$> expectedR- pure $ Record- (Dhall.Map.fromList- [ (nameL, l)- , (nameR, r)- ]- )-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of- Just (expressionL, expressionR) ->- liftA2 (:*:)- (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))- (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))- Nothing -> die- _ -> die-- return (Decoder {..})--instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where- genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do- let n :: M1 S s (K1 i a) r- n = undefined-- name <- fmap fieldModifier (getSelName n)-- let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer-- let expected =- case singletonConstructors of- Bare ->- expected'- Smart | selName n == "" ->- expected'- _ ->- Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'-- let extract0 expression = fmap (M1 . K1) (extract' expression)-- let extract1 expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of- Just subExpression ->- fmap (M1 . K1) (extract' subExpression)- Nothing ->- die- _ -> die-- let extract =- case singletonConstructors of- Bare -> extract0- Smart | selName n == "" -> extract0- _ -> extract1-- return (Decoder {..})--{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from- Haskell into Dhall--}-data Encoder a = Encoder- { embed :: a -> Expr Src Void- -- ^ Embeds a Haskell value as a Dhall expression- , declared :: Expr Src Void- -- ^ Dhall type of the Haskell value- }--instance Contravariant Encoder where- contramap f (Encoder embed declared) = Encoder embed' declared- where- embed' x = embed (f x)--{-| This class is used by `FromDhall` instance for functions:--> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)-- You can convert Dhall functions with "simple" inputs (i.e. instances of this- class) into Haskell functions. This works by:-- * Marshaling the input to the Haskell function into a Dhall expression (i.e.- @x :: Expr Src Void@)- * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input- (i.e. @App f x@)- * Normalizing the syntax tree (i.e. @normalize (App f x)@)- * Marshaling the resulting Dhall expression back into a Haskell value-- This class auto-generates a default implementation for types that- implement `Generic`. This does not auto-generate an instance for recursive- types.-- The default instance can be tweaked using 'genericToDhallWith' and custom- 'InterpretOptions', or using- [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)- and 'Dhall.Deriving.Codec' from "Dhall.Deriving".--}-class ToDhall a where- injectWith :: InputNormalizer -> Encoder a- default injectWith- :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a- injectWith _ = genericToDhall---- | A compatibility alias for `ToDhall`-type Inject = ToDhall-{-# DEPRECATED Inject "Use ToDhall instead" #-}--{-| Use the default input normalizer for injecting a value--> inject = injectWith defaultInputNormalizer--}-inject :: ToDhall a => Encoder a-inject = injectWith defaultInputNormalizer--{-| Use the default options for injecting a value, whose structure is-determined generically.--This can be used when you want to use 'ToDhall' on types that you don't-want to define orphan instances for.--}-genericToDhall- :: (Generic a, GenericToDhall (Rep a)) => Encoder a-genericToDhall- = genericToDhallWith defaultInterpretOptions--{-| Use custom options for injecting a value, whose structure is-determined generically.--This can be used when you want to use 'ToDhall' on types that you don't-want to define orphan instances for.--}-genericToDhallWith- :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a-genericToDhallWith options- = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer defaultInputNormalizer options) 1)--instance ToDhall Void where- injectWith _ = Encoder {..}- where- embed = Data.Void.absurd-- declared = Union mempty--instance ToDhall Bool where- injectWith _ = Encoder {..}- where- embed = BoolLit-- declared = Bool--instance ToDhall Data.Text.Lazy.Text where- injectWith _ = Encoder {..}- where- embed text =- TextLit (Chunks [] (Data.Text.Lazy.toStrict text))-- declared = Text--instance ToDhall Text where- injectWith _ = Encoder {..}- where- embed text = TextLit (Chunks [] text)-- declared = Text--instance {-# OVERLAPS #-} ToDhall String where- injectWith inputNormalizer =- contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)--instance ToDhall Natural where- injectWith _ = Encoder {..}- where- embed = NaturalLit-- declared = Natural--instance ToDhall Integer where- injectWith _ = Encoder {..}- where- embed = IntegerLit-- declared = Integer--instance ToDhall Int where- injectWith _ = Encoder {..}- where- embed = IntegerLit . toInteger-- declared = Integer--{-|-->>> embed inject (12 :: Word)-NaturalLit 12--}--instance ToDhall Word where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word8)-NaturalLit 12--}--instance ToDhall Word8 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word16)-NaturalLit 12--}--instance ToDhall Word16 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word32)-NaturalLit 12--}--instance ToDhall Word32 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word64)-NaturalLit 12--}--instance ToDhall Word64 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--instance ToDhall Double where- injectWith _ = Encoder {..}- where- embed = DoubleLit . DhallDouble-- declared = Double--instance ToDhall Scientific where- injectWith inputNormalizer =- contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)--instance ToDhall () where- injectWith _ = Encoder {..}- where- embed = const (RecordLit mempty)-- declared = Record mempty--instance ToDhall a => ToDhall (Maybe a) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut (Just x ) = Some (embedIn x)- embedOut Nothing = App None declaredIn-- Encoder embedIn declaredIn = injectWith inputNormalizer-- declaredOut = App Optional declaredIn--instance ToDhall a => ToDhall (Seq a) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut xs = ListLit listType (fmap embedIn xs)- where- listType- | null xs = Just (App List declaredIn)- | otherwise = Nothing-- declaredOut = App List declaredIn-- Encoder embedIn declaredIn = injectWith inputNormalizer--instance ToDhall a => ToDhall [a] where- injectWith = fmap (contramap Data.Sequence.fromList) injectWith--instance ToDhall a => ToDhall (Vector a) where- injectWith = fmap (contramap Data.Vector.toList) injectWith--{-| Note that the output list will be sorted-->>> let x = Data.Set.fromList ["mom", "hi" :: Text]->>> prettyExpr $ embed inject x-[ "hi", "mom" ]---}-instance ToDhall a => ToDhall (Data.Set.Set a) where- injectWith = fmap (contramap Data.Set.toAscList) injectWith---- | Note that the output list may not be sorted-instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where- injectWith = fmap (contramap Data.HashSet.toList) injectWith--instance (ToDhall a, ToDhall b) => ToDhall (a, b)--{-| Embed a `Data.Map` as a @Prelude.Map.Type@-->>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])-[ { mapKey = 1, mapValue = True } ]-->>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)-[] : List { mapKey : Natural, mapValue : Bool }---}-instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut m = ListLit listType (mapEntries m)- where- listType- | Data.Map.null m = Just declaredOut- | otherwise = Nothing-- declaredOut = App List (Record $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField declaredK)- , ("mapValue", Core.makeRecordField declaredV)- ])-- mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList- recordPair (k, v) = RecordLit $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField $ embedK k)- , ("mapValue", Core.makeRecordField $ embedV v)- ]-- Encoder embedK declaredK = injectWith inputNormalizer- Encoder embedV declaredV = injectWith inputNormalizer--{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@-->>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])-[ { mapKey = 1, mapValue = True } ]-->>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)-[] : List { mapKey : Natural, mapValue : Bool }---}-instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut m = ListLit listType (mapEntries m)- where- listType- | HashMap.null m = Just declaredOut- | otherwise = Nothing-- declaredOut = App List (Record $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField declaredK)- , ("mapValue", Core.makeRecordField declaredV)- ])-- mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList- recordPair (k, v) = RecordLit $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField $ embedK k)- , ("mapValue", Core.makeRecordField $ embedV v)- ]-- Encoder embedK declaredK = injectWith inputNormalizer- Encoder embedV declaredV = injectWith inputNormalizer--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation--}-class GenericToDhall f where- genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))--instance GenericToDhall f => GenericToDhall (M1 D d f) where- genericToDhallWithNormalizer inputNormalizer options = do- res <- genericToDhallWithNormalizer inputNormalizer options- pure (contramap unM1 res)--instance GenericToDhall f => GenericToDhall (M1 C c f) where- genericToDhallWithNormalizer inputNormalizer options = do- res <- genericToDhallWithNormalizer inputNormalizer options- pure (contramap unM1 res)--instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where- genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do- let Encoder { embed = embed', declared = declared' } =- injectWith inputNormalizer-- let n :: M1 S s (K1 i a) r- n = undefined-- name <- fieldModifier <$> getSelName n-- let embed0 (M1 (K1 x)) = embed' x-- let embed1 (M1 (K1 x)) =- RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))-- let embed =- case singletonConstructors of- Bare -> embed0- Smart | selName n == "" -> embed0- _ -> embed1-- let declared =- case singletonConstructors of- Bare ->- declared'- Smart | selName n == "" ->- declared'- _ ->- Record (Dhall.Map.singleton name $ Core.makeRecordField declared')-- return (Encoder {..})--instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 (M1 l)) =- case notEmptyRecordLit (embedL l) of- Nothing ->- Field declared $ Core.makeFieldSelection keyL- Just valL ->- App (Field declared $ Core.makeFieldSelection keyL) valL-- embed (R1 (M1 r)) =- case notEmptyRecordLit (embedR r) of- Nothing ->- Field declared $ Core.makeFieldSelection keyR- Just valR ->- App (Field declared $ Core.makeFieldSelection keyR) valR-- declared =- Union- (Dhall.Map.fromList- [ (keyL, notEmptyRecord declaredL)- , (keyR, notEmptyRecord declaredR)- ]- )-- nL :: M1 i c1 f1 a- nL = undefined-- nR :: M1 i c2 f2 a- nR = undefined-- keyL = constructorModifier (Data.Text.pack (conName nL))- keyR = constructorModifier (Data.Text.pack (conName nR))-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1--instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 l) =- case maybeValL of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- where- (keyL, maybeValL) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)- embed (R1 (M1 r)) =- case notEmptyRecordLit (embedR r) of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR-- nR :: M1 i c h a- nR = undefined-- keyR = constructorModifier (Data.Text.pack (conName nR))-- declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL--instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 (M1 l)) =- case notEmptyRecordLit (embedL l) of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- embed (R1 r) =- case maybeValR of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR- where- (keyR, maybeValR) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)-- nL :: M1 i c f a- nL = undefined-- keyL = constructorModifier (Data.Text.pack (conName nL))-- declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR--instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where- genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})- where- embed (L1 l) =- case maybeValL of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- where- (keyL, maybeValL) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)- embed (R1 r) =- case maybeValR of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR- where- (keyR, maybeValR) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)-- declared = Union (Dhall.Map.union ktsL ktsR)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL- ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR--instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where- genericToDhallWithNormalizer inputNormalizer options = do- Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options- Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options-- let embed (l :*: r) =- RecordLit (Dhall.Map.union mapL mapR)- where- mapL =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)-- mapR =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)-- let declared = Record (Dhall.Map.union mapL mapR)- where- mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL- mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR-- pure (Encoder {..})--instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where- genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do- let nR :: M1 S s (K1 i a) r- nR = undefined-- nameR <- fmap fieldModifier (getSelName nR)-- Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options-- let Encoder embedR declaredR = injectWith inputNormalizer-- let embed (l :*: M1 (K1 r)) =- RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)- where- mapL =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)-- let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)- where- mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL-- return (Encoder {..})--instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where- genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do- let nL :: M1 S s (K1 i a) r- nL = undefined-- nameL <- fmap fieldModifier (getSelName nL)-- let Encoder embedL declaredL = injectWith inputNormalizer-- Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options-- let embed (M1 (K1 l) :*: r) =- RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)- where- mapR =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)-- let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)- where- mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR-- return (Encoder {..})--instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do- let nL :: M1 S s1 (K1 i1 a1) r- nL = undefined-- let nR :: M1 S s2 (K1 i2 a2) r- nR = undefined-- nameL <- fmap fieldModifier (getSelName nL)- nameR <- fmap fieldModifier (getSelName nR)-- let Encoder embedL declaredL = injectWith inputNormalizer- let Encoder embedR declaredR = injectWith inputNormalizer-- let embed (M1 (K1 l) :*: M1 (K1 r)) =- RecordLit $- Dhall.Map.fromList- [ (nameL, Core.makeRecordField $ embedL l)- , (nameR, Core.makeRecordField $ embedR r) ]--- let declared =- Record $ Dhall.Map.fromList- [ (nameL, Core.makeRecordField declaredL)- , (nameR, Core.makeRecordField declaredR) ]--- return (Encoder {..})--instance GenericToDhall U1 where- genericToDhallWithNormalizer _ _ = pure (Encoder {..})- where- embed _ = RecordLit mempty-- declared = Record mempty--{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'- from a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Project = Project- { projectName :: Text- , projectDescription :: Text- , projectStars :: Natural- }-:}-- And assume that we have the following Dhall record that we would like to- parse as a @Project@:--> { name =-> "dhall-haskell"-> , description =-> "A configuration language guaranteed to terminate"-> , stars =-> 289-> }-- Our decoder has type 'Decoder' @Project@, but we can't build that out of any- smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).- However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:-->>> :{-project :: Decoder Project-project =- record- ( Project <$> field "name" strictText- <*> field "description" strictText- <*> field "stars" natural- )-:}--}--newtype RecordDecoder a =- RecordDecoder- ( Data.Functor.Product.Product- ( Control.Applicative.Const- (Dhall.Map.Map Text (Expector (Expr Src Void)))- )- ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)- )- a- )- deriving (Functor, Applicative)----- | Run a 'RecordDecoder' to build a 'Decoder'.-record :: RecordDecoder a -> Dhall.Decoder a-record- (RecordDecoder- (Data.Functor.Product.Pair- (Control.Applicative.Const fields)- (Data.Functor.Compose.Compose extract)- )- ) = Decoder {..}- where- expected = Record <$> traverse (fmap Core.makeRecordField) fields----- | Parse a single field of a record.-field :: Text -> Decoder a -> RecordDecoder a-field key (Decoder {..}) =- RecordDecoder- ( Data.Functor.Product.Pair- ( Control.Applicative.Const- (Dhall.Map.singleton key expected)- )- ( Data.Functor.Compose.Compose extractBody )- )- where- extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of- Just v -> extract v- _ -> typeError expected expr- extractBody expr = typeError expected expr--{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union-- For example, let's take the following Haskell data type:-->>> :{-data Status = Queued Natural- | Result Text- | Errored Text-:}-- And assume that we have the following Dhall union that we would like to- parse as a @Status@:--> < Result : Text-> | Queued : Natural-> | Errored : Text-> >.Result "Finish successfully"-- Our decoder has type 'Decoder' @Status@, but we can't build that out of any- smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).- However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:-->>> :{-status :: Decoder Status-status = union- ( ( Queued <$> constructor "Queued" natural )- <> ( Result <$> constructor "Result" strictText )- <> ( Errored <$> constructor "Errored" strictText )- )-:}---}-newtype UnionDecoder a =- UnionDecoder- ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )- deriving (Functor)--instance Semigroup (UnionDecoder a) where- (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))--instance Monoid (UnionDecoder a) where- mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))---- | Run a 'UnionDecoder' to build a 'Decoder'.-union :: UnionDecoder a -> Decoder a-union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}- where- extract expr = case expected' of- Failure e -> Failure $ fmap ExpectedTypeError e- Success x -> extract' expr x-- extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.extract) $ do- (fld, e1, rest) <- extractUnionConstructor e0-- t <- Dhall.Map.lookup fld mp-- guard $- Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')-- pure (t, e1)-- expected = Union <$> expected'-- expected' = traverse (fmap notEmptyRecord . Dhall.expected) mp---- | Parse a single constructor of a union-constructor :: Text -> Decoder a -> UnionDecoder a-constructor key valueDecoder = UnionDecoder- ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )---- | Infix 'divided'-(>*<) :: Divisible f => f a -> f b -> f (a, b)-(>*<) = divided--infixr 5 >*<--{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build- an 'Encoder' for a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Project = Project- { projectName :: Text- , projectDescription :: Text- , projectStars :: Natural- }-:}-- And assume that we have the following Dhall record that we would like to- parse as a @Project@:--> { name =-> "dhall-haskell"-> , description =-> "A configuration language guaranteed to terminate"-> , stars =-> 289-> }-- Our encoder has type 'Encoder' @Project@, but we can't build that out of any- smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).- However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:-->>> :{-injectProject :: Encoder Project-injectProject =- recordEncoder- ( adapt >$< encodeFieldWith "name" inject- >*< encodeFieldWith "description" inject- >*< encodeFieldWith "stars" inject- )- where- adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}-- Or, since we are simply using the `ToDhall` instance to inject each field, we could write-->>> :{-injectProject :: Encoder Project-injectProject =- recordEncoder- ( adapt >$< encodeField "name"- >*< encodeField "description"- >*< encodeField "stars"- )- where- adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}---}--newtype RecordEncoder a- = RecordEncoder (Dhall.Map.Map Text (Encoder a))--instance Contravariant RecordEncoder where- contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord--instance Divisible RecordEncoder where- divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =- RecordEncoder- $ Dhall.Map.union- ((contramap $ fst . f) <$> bEncoderRecord)- ((contramap $ snd . f) <$> cEncoderRecord)- conquer = RecordEncoder mempty--{-| Specify how to encode one field of a record by supplying an explicit- `Encoder` for that field--}-encodeFieldWith :: Text -> Encoder a -> RecordEncoder a-encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType--{-| Specify how to encode one field of a record using the default `ToDhall`- instance for that type--}-encodeField :: ToDhall a => Text -> RecordEncoder a-encodeField name = encodeFieldWith name inject---- | Convert a `RecordEncoder` into the equivalent `Encoder`-recordEncoder :: RecordEncoder a -> Encoder a-recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType- where- recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord- makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord--{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Status = Queued Natural- | Result Text- | Errored Text-:}-- And assume that we have the following Dhall union that we would like to- parse as a @Status@:--> < Result : Text-> | Queued : Natural-> | Errored : Text-> >.Result "Finish successfully"-- Our encoder has type 'Encoder' @Status@, but we can't build that out of any- smaller encoders, as 'Encoder's cannot be combined.- However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:-->>> :{-injectStatus :: Encoder Status-injectStatus = adapt >$< unionEncoder- ( encodeConstructorWith "Queued" inject- >|< encodeConstructorWith "Result" inject- >|< encodeConstructorWith "Errored" inject- )- where- adapt (Queued n) = Left n- adapt (Result t) = Right (Left t)- adapt (Errored e) = Right (Right e)-:}-- Or, since we are simply using the `ToDhall` instance to inject each branch, we could write-->>> :{-injectStatus :: Encoder Status-injectStatus = adapt >$< unionEncoder- ( encodeConstructor "Queued"- >|< encodeConstructor "Result"- >|< encodeConstructor "Errored"- )- where- adapt (Queued n) = Left n- adapt (Result t) = Right (Left t)- adapt (Errored e) = Right (Right e)-:}---}-newtype UnionEncoder a =- UnionEncoder- ( Data.Functor.Product.Product- ( Control.Applicative.Const- ( Dhall.Map.Map- Text- ( Expr Src Void )- )- )- ( Op (Text, Expr Src Void) )- a- )- deriving (Contravariant)---- | Combines two 'UnionEncoder' values. See 'UnionEncoder' for usage--- notes.------ Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';--- however, this allows 'UnionEncoder' to not need a 'Divisible' instance--- itself (since no instance is possible).-(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)-UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))- >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =- UnionEncoder- ( Data.Functor.Product.Pair- ( Control.Applicative.Const (mx <> my) )- ( Op (either fx fy) )- )--infixr 5 >|<---- | Convert a `UnionEncoder` into the equivalent `Encoder`-unionEncoder :: UnionEncoder a -> Encoder a-unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =- Encoder- { embed = \x ->- let (name, y) = embedF x- in case notEmptyRecordLit y of- Nothing -> Field (Union fields') $ Core.makeFieldSelection name- Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val- , declared =- Union fields'- }- where- fields' = fmap notEmptyRecord fields--{-| Specify how to encode an alternative by providing an explicit `Encoder`- for that alternative--}-encodeConstructorWith- :: Text- -> Encoder a- -> UnionEncoder a-encodeConstructorWith name encodeType = UnionEncoder $- Data.Functor.Product.Pair- ( Control.Applicative.Const- ( Dhall.Map.singleton- name- ( declared encodeType )- )- )- ( Op ( (name,) . embed encodeType )- )--{-| Specify how to encode an alternative by using the default `ToDhall` instance- for that type--}-encodeConstructor- :: ToDhall a- => Text- -> UnionEncoder a-encodeConstructor name = encodeConstructorWith name inject+ , module Dhall.Marshal.Decode++ -- * Encoders+ , module Dhall.Marshal.Encode++ -- * Miscellaneous+ , rawInput+ ) where++import Control.Applicative (Alternative, empty)+import Data.Either.Validation (Validation (..))+import Data.Void (Void)+import Dhall.Import (Imported (..))+import Dhall.Parser (Src (..))+import Dhall.Syntax (Expr (..))+import Dhall.TypeCheck (DetailedTypeError (..), TypeError)+import GHC.Generics+import Lens.Family (LensLike', view)+import Prelude hiding (maybe, sequence)+import System.FilePath (takeDirectory)++import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Text.IO+import qualified Dhall.Context+import qualified Dhall.Core as Core+import qualified Dhall.Import+import qualified Dhall.Parser+import qualified Dhall.Pretty.Internal+import qualified Dhall.Substitution+import qualified Dhall.TypeCheck+import qualified Lens.Family++import Dhall.Marshal.Decode+import Dhall.Marshal.Encode++-- | @since 1.16+data InputSettings = InputSettings+ { _rootDirectory :: FilePath+ , _sourceName :: FilePath+ , _evaluateSettings :: EvaluateSettings+ }++-- | Default input settings: resolves imports relative to @.@ (the+-- current working directory), report errors as coming from @(input)@,+-- and default evaluation settings from 'defaultEvaluateSettings'.+--+-- @since 1.16+defaultInputSettings :: InputSettings+defaultInputSettings = InputSettings+ { _rootDirectory = "."+ , _sourceName = "(input)"+ , _evaluateSettings = defaultEvaluateSettings+ }+++-- | Access the directory to resolve imports relative to.+--+-- @since 1.16+rootDirectory+ :: (Functor f)+ => LensLike' f InputSettings FilePath+rootDirectory k s =+ fmap (\x -> s { _rootDirectory = x }) (k (_rootDirectory s))++-- | Access the name of the source to report locations from; this is+-- only used in error messages, so it's okay if this is a best guess+-- or something symbolic.+--+-- @since 1.16+sourceName+ :: (Functor f)+ => LensLike' f InputSettings FilePath+sourceName k s =+ fmap (\x -> s { _sourceName = x}) (k (_sourceName s))++-- | @since 1.16+data EvaluateSettings = EvaluateSettings+ { _substitutions :: Dhall.Substitution.Substitutions Src Void+ , _startingContext :: Dhall.Context.Context (Expr Src Void)+ , _normalizer :: Maybe (Core.ReifiedNormalizer Void)+ , _newManager :: IO Dhall.Import.Manager+ }++-- | Default evaluation settings: no extra entries in the initial+-- context, and no special normalizer behaviour.+--+-- @since 1.16+defaultEvaluateSettings :: EvaluateSettings+defaultEvaluateSettings = EvaluateSettings+ { _substitutions = Dhall.Substitution.empty+ , _startingContext = Dhall.Context.empty+ , _normalizer = Nothing+ , _newManager = Dhall.Import.defaultNewManager+ }++-- | Access the starting context used for evaluation and type-checking.+--+-- @since 1.16+startingContext+ :: (Functor f, HasEvaluateSettings s)+ => LensLike' f s (Dhall.Context.Context (Expr Src Void))+startingContext = evaluateSettings . l+ where+ l :: (Functor f)+ => LensLike' f EvaluateSettings (Dhall.Context.Context (Expr Src Void))+ l k s = fmap (\x -> s { _startingContext = x}) (k (_startingContext s))++-- | Access the custom substitutions.+--+-- @since 1.30+substitutions+ :: (Functor f, HasEvaluateSettings s)+ => LensLike' f s (Dhall.Substitution.Substitutions Src Void)+substitutions = evaluateSettings . l+ where+ l :: (Functor f)+ => LensLike' f EvaluateSettings (Dhall.Substitution.Substitutions Src Void)+ l k s = fmap (\x -> s { _substitutions = x }) (k (_substitutions s))++-- | Access the custom normalizer.+--+-- @since 1.16+normalizer+ :: (Functor f, HasEvaluateSettings s)+ => LensLike' f s (Maybe (Core.ReifiedNormalizer Void))+normalizer = evaluateSettings . l+ where+ l :: (Functor f)+ => LensLike' f EvaluateSettings (Maybe (Core.ReifiedNormalizer Void))+ l k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s))++-- | Access the HTTP manager initializer.+--+-- @since 1.36+newManager+ :: (Functor f, HasEvaluateSettings s)+ => LensLike' f s (IO Dhall.Import.Manager)+newManager = evaluateSettings . l+ where+ l :: (Functor f)+ => LensLike' f EvaluateSettings (IO Dhall.Import.Manager)+ l k s = fmap (\x -> s { _newManager = x }) (k (_newManager s))++-- | @since 1.16+class HasEvaluateSettings s where+ evaluateSettings+ :: (Functor f)+ => LensLike' f s EvaluateSettings++instance HasEvaluateSettings InputSettings where+ evaluateSettings k s =+ fmap (\x -> s { _evaluateSettings = x }) (k (_evaluateSettings s))++instance HasEvaluateSettings EvaluateSettings where+ evaluateSettings = id++{-| Type-check and evaluate a Dhall program, decoding the result into Haskell++ The first argument determines the type of value that you decode:++>>> input integer "+2"+2+>>> input (vector double) "[1.0, 2.0]"+[1.0,2.0]++ Use `auto` to automatically select which type to decode based on the+ inferred return type:++>>> input auto "True" :: IO Bool+True++ This uses the settings from 'defaultInputSettings'.+-}+input+ :: Decoder a+ -- ^ The decoder for the Dhall value+ -> Text+ -- ^ The Dhall program+ -> IO a+ -- ^ The decoded value in Haskell+input =+ inputWithSettings defaultInputSettings++{-| Extend 'input' with a root directory to resolve imports relative+ to, a file to mention in errors as the source, a custom typing+ context, and a custom normalization process.++@since 1.16+-}+inputWithSettings+ :: InputSettings+ -> Decoder a+ -- ^ The decoder for the Dhall value+ -> Text+ -- ^ The Dhall program+ -> IO a+ -- ^ The decoded value in Haskell+inputWithSettings settings (Decoder {..}) txt = do+ expected' <- case expected of+ Success x -> return x+ Failure e -> Control.Exception.throwIO e++ let suffix = Dhall.Pretty.Internal.prettyToStrictText expected'+ let annotate substituted = case substituted of+ Note (Src begin end bytes) _ ->+ Note (Src begin end bytes') (Annot substituted expected')+ where+ bytes' = bytes <> " : " <> suffix+ _ ->+ Annot substituted expected'++ normExpr <- inputHelper annotate settings txt++ case extract normExpr of+ Success x -> return x+ Failure e -> Control.Exception.throwIO e++{-| Type-check and evaluate a Dhall program that is read from the+ file-system.++ This uses the settings from 'defaultEvaluateSettings'.++ @since 1.16+-}+inputFile+ :: Decoder a+ -- ^ The decoder for the Dhall value+ -> FilePath+ -- ^ The path to the Dhall program.+ -> IO a+ -- ^ The decoded value in Haskell.+inputFile =+ inputFileWithSettings defaultEvaluateSettings++{-| Extend 'inputFile' with a custom typing context and a custom+ normalization process.++@since 1.16+-}+inputFileWithSettings+ :: EvaluateSettings+ -> Decoder a+ -- ^ The decoder for the Dhall value+ -> FilePath+ -- ^ The path to the Dhall program.+ -> IO a+ -- ^ The decoded value in Haskell.+inputFileWithSettings settings ty path = do+ text <- Data.Text.IO.readFile path+ let inputSettings = InputSettings+ { _rootDirectory = takeDirectory path+ , _sourceName = path+ , _evaluateSettings = settings+ }+ inputWithSettings inputSettings ty text++{-| Similar to `input`, but without interpreting the Dhall `Expr` into a Haskell+ type.++ Uses the settings from 'defaultInputSettings'.+-}+inputExpr+ :: Text+ -- ^ The Dhall program+ -> IO (Expr Src Void)+ -- ^ The fully normalized AST+inputExpr =+ inputExprWithSettings defaultInputSettings++{-| Extend 'inputExpr' with a root directory to resolve imports relative+ to, a file to mention in errors as the source, a custom typing+ context, and a custom normalization process.++@since 1.16+-}+inputExprWithSettings+ :: InputSettings+ -> Text+ -- ^ The Dhall program+ -> IO (Expr Src Void)+ -- ^ The fully normalized AST+inputExprWithSettings = inputHelper id++{-| Helper function for the input* function family++@since 1.30+-}+inputHelper+ :: (Expr Src Void -> Expr Src Void)+ -> InputSettings+ -> Text+ -- ^ The Dhall program+ -> IO (Expr Src Void)+ -- ^ The fully normalized AST+inputHelper annotate settings txt = do+ expr <- Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)++ let InputSettings {..} = settings++ let EvaluateSettings {..} = _evaluateSettings++ let transform =+ Lens.Family.set Dhall.Import.substitutions _substitutions+ . Lens.Family.set Dhall.Import.normalizer _normalizer+ . Lens.Family.set Dhall.Import.startingContext _startingContext++ let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)++ expr' <- State.evalStateT (Dhall.Import.loadWith expr) status++ let substituted = Dhall.Substitution.substitute expr' $ view substitutions settings+ let annot = annotate substituted+ _ <- Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot)+ pure (Core.normalizeWith (view normalizer settings) substituted)++-- | Use this function to extract Haskell values directly from Dhall AST.+-- The intended use case is to allow easy extraction of Dhall values for+-- making the function `Core.normalizeWith` easier to use.+--+-- For other use cases, use `input` from "Dhall" module. It will give you+-- a much better user experience.+rawInput+ :: Alternative f+ => Decoder a+ -- ^ The decoder for the Dhall value+ -> Expr s Void+ -- ^ a closed form Dhall program, which evaluates to the expected type+ -> f a+ -- ^ The decoded value in Haskell+rawInput (Decoder {..}) expr =+ case extract (Core.normalize expr) of+ Success x -> pure x+ Failure _e -> empty++{-| Use this to provide more detailed error messages++>> input auto "True" :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> True : Integer+>+> (input):1:1++>> detailed (input auto "True") :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> Explanation: You can annotate an expression with its type or kind using the+> ❰:❱ symbol, like this:+>+>+> ┌───────┐+> │ x : t │ ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱+> └───────┘+>+> The type checker verifies that the expression's type or kind matches the+> provided annotation+>+> For example, all of the following are valid annotations that the type checker+> accepts:+>+>+> ┌─────────────┐+> │ 1 : Natural │ ❰1❱ is an expression that has type ❰Natural❱, so the type+> └─────────────┘ checker accepts the annotation+>+>+> ┌───────────────────────┐+> │ Natural/even 2 : Bool │ ❰Natural/even 2❱ has type ❰Bool❱, so the type+> └───────────────────────┘ checker accepts the annotation+>+>+> ┌────────────────────┐+> │ List : Type → Type │ ❰List❱ is an expression that has kind ❰Type → Type❱,+> └────────────────────┘ so the type checker accepts the annotation+>+>+> ┌──────────────────┐+> │ List Text : Type │ ❰List Text❱ is an expression that has kind ❰Type❱, so+> └──────────────────┘ the type checker accepts the annotation+>+>+> However, the following annotations are not valid and the type checker will+> reject them:+>+>+> ┌──────────┐+> │ 1 : Text │ The type checker rejects this because ❰1❱ does not have type+> └──────────┘ ❰Text❱+>+>+> ┌─────────────┐+> │ List : Type │ ❰List❱ does not have kind ❰Type❱+> └─────────────┘+>+>+> You or the interpreter annotated this expression:+>+> ↳ True+>+> ... with this type or kind:+>+> ↳ Integer+>+> ... but the inferred type or kind of the expression is actually:+>+> ↳ Bool+>+> Some common reasons why you might get this error:+>+> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation+> matching the expected type+>+> For example, if you run the following Haskell code:+>+>+> ┌───────────────────────────────┐+> │ >>> input auto "1" :: IO Text │+> └───────────────────────────────┘+>+>+> ... then the interpreter will actually type check the following annotated+> expression:+>+>+> ┌──────────┐+> │ 1 : Text │+> └──────────┘+>+>+> ... and then type-checking will fail+>+> ────────────────────────────────────────────────────────────────────────────────+>+> True : Integer+>+> (input):1:1++-}+detailed :: IO a -> IO a+detailed =+ Control.Exception.handle handler1 . Control.Exception.handle handler0+ where+ handler0 :: Imported (TypeError Src Void) -> IO a+ handler0 (Imported ps e) =+ Control.Exception.throwIO (Imported ps (DetailedTypeError e))++ handler1 :: TypeError Src Void -> IO a+ handler1 e = Control.Exception.throwIO (DetailedTypeError e)
src/Dhall/Binary.hs view
@@ -13,15 +13,11 @@ -} module Dhall.Binary- ( -- * Standard versions- StandardVersion(..)- , renderStandardVersion-- -- * Encoding and decoding- , encodeExpression+ ( -- * Encoding and decoding+ encodeExpression , decodeExpression - -- * Exceptions+ -- * Exceptions , DecodingFailure(..) ) where @@ -54,7 +50,6 @@ ) import Data.Foldable (toList)-import Data.Text (Text) import Data.Void (Void, absurd) import GHC.Float (double2Float, float2Double) import Numeric.Half (fromHalf, toHalf)@@ -76,35 +71,6 @@ import qualified Dhall.Syntax as Syntax import qualified Text.Printf as Printf -{-| Supported version strings-- This exists primarily for backwards compatibility for expressions encoded- before Dhall removed version tags from the binary encoding--}-data StandardVersion- = NoVersion- -- ^ No version string- | V_5_0_0- -- ^ Version "5.0.0"- | V_4_0_0- -- ^ Version "4.0.0"- | V_3_0_0- -- ^ Version "3.0.0"- | V_2_0_0- -- ^ Version "2.0.0"- | V_1_0_0- -- ^ Version "1.0.0"- deriving (Enum, Bounded)---- | Render a `StandardVersion` as `Data.Text.Text`-renderStandardVersion :: StandardVersion -> Text-renderStandardVersion NoVersion = "none"-renderStandardVersion V_1_0_0 = "1.0.0"-renderStandardVersion V_2_0_0 = "2.0.0"-renderStandardVersion V_3_0_0 = "3.0.0"-renderStandardVersion V_4_0_0 = "4.0.0"-renderStandardVersion V_5_0_0 = "5.0.0"- {-| Convert a function applied to multiple arguments to the base function and the list of arguments -}@@ -319,7 +285,7 @@ 9 -> return (Prefer mempty PreferFromSource) 10 -> return (CombineTypes mempty) 11 -> return ImportAlt- 12 -> return Equivalent+ 12 -> return (Equivalent mempty) 13 -> return RecordCompletion _ -> die ("Unrecognized operator code: " <> show opcode) @@ -792,7 +758,7 @@ ImportAlt l r -> encodeOperator 11 l r - Equivalent l r ->+ Equivalent _ l r -> encodeOperator 12 l r RecordCompletion l r ->
src/Dhall/Diff.hs view
@@ -992,7 +992,7 @@ diffEquivalentExpression l@(Equivalent {}) r@(Equivalent {}) = enclosed' " " (operator "≡" <> " ") (docs l r) where- docs (Equivalent aL bL) (Equivalent aR bR) =+ docs (Equivalent _ aL bL) (Equivalent _ aR bR) = Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR) docs aL aR = pure (diffApplicationExpression aL aR)
src/Dhall/Eval.hs view
@@ -134,6 +134,10 @@ -- ^ The original function was a @Natural/subtract 0@. We need to preserve -- this information in case the @Natural/subtract@ ends up not being fully -- saturated, in which case we need to recover the unsaturated built-in+ | TextReplaceEmpty+ -- ^ The original function was a @Text/replace ""@+ | TextReplaceEmptyArgument (Val a)+ -- ^ The original function was a @Text/replace "" replacement@ deriving instance (Show a, Show (Val a -> Val a)) => Show (HLamInfo a) @@ -603,33 +607,43 @@ t -> VTextShow t TextReplace -> VPrim $ \needle ->- VPrim $ \replacement ->- VPrim $ \haystack ->- case needle of+ let hLamInfo0 = case needle of+ VTextLit (VChunks [] "") -> TextReplaceEmpty+ _ -> Prim++ in VHLam hLamInfo0 $ \replacement ->+ let hLamInfo1 = case needle of VTextLit (VChunks [] "") ->- haystack- VTextLit (VChunks [] needleText) ->- case haystack of- VTextLit (VChunks [] haystackText) ->- case replacement of- VTextLit (VChunks [] replacementText) ->- VTextLit $ VChunks []- (Text.replace- needleText- replacementText- haystackText- )- _ ->- VTextLit- (vTextReplace- needleText- replacement- haystackText- )- _ ->- VTextReplace needle replacement haystack+ TextReplaceEmptyArgument replacement _ ->- VTextReplace needle replacement haystack+ Prim+ in VHLam hLamInfo1 $ \haystack ->+ case needle of+ VTextLit (VChunks [] "") ->+ haystack++ VTextLit (VChunks [] needleText) ->+ case haystack of+ VTextLit (VChunks [] haystackText) ->+ case replacement of+ VTextLit (VChunks [] replacementText) ->+ VTextLit $ VChunks []+ (Text.replace+ needleText+ replacementText+ haystackText+ )+ _ ->+ VTextLit+ (vTextReplace+ needleText+ replacement+ haystackText+ )+ _ ->+ VTextReplace needle replacement haystack+ _ ->+ VTextReplace needle replacement haystack List -> VPrim VList ListLit ma ts ->@@ -787,7 +801,7 @@ VProject (eval env t) (Right e') Assert t -> VAssert (eval env t)- Equivalent t u ->+ Equivalent _ t u -> VEquivalent (eval env t) (eval env u) With e₀ ks v -> vWith (eval env e₀) ks (eval env v)@@ -1062,12 +1076,18 @@ VHLam i t -> case i of Typed (fresh -> (x, v)) a ->- Lam- mempty+ Lam mempty (Syntax.makeFunctionBinding x (quote env a)) (quoteBind x (t v))- Prim -> quote env (t VPrimVar)- NaturalSubtractZero -> App NaturalSubtract (NaturalLit 0)+ Prim ->+ quote env (t VPrimVar)+ NaturalSubtractZero ->+ App NaturalSubtract (NaturalLit 0)+ TextReplaceEmpty ->+ App TextReplace (TextLit (Chunks [] ""))+ TextReplaceEmptyArgument replacement ->+ App (App TextReplace (TextLit (Chunks [] "")))+ (quote env replacement) VPi a (freshClosure -> (x, v, b)) -> Pi mempty x (quote env a) (quoteBind x (instantiate b v))@@ -1188,7 +1208,7 @@ VAssert t -> Assert (quote env t) VEquivalent t u ->- Equivalent (quote env t) (quote env u)+ Equivalent mempty (quote env t) (quote env u) VWith e ks v -> With (quote env e) ks (quote env v) VInject m k Nothing ->@@ -1374,8 +1394,8 @@ Project (go t) (fmap go ks) Assert t -> Assert (go t)- Equivalent t u ->- Equivalent (go t) (go u)+ Equivalent cs t u ->+ Equivalent cs (go t) (go u) With e k v -> With (go e) k (go v) Note s e ->
src/Dhall/Format.hs view
@@ -11,19 +11,24 @@ , format ) where -import Data.Foldable (for_)-import Data.Maybe (fromMaybe)-import Dhall.Pretty (CharacterSet, annToAnsiStyle, detectCharacterSet)+import Data.Foldable (for_)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe (fromMaybe)+import Dhall.Pretty+ ( CharacterSet+ , annToAnsiStyle+ , detectCharacterSet+ ) import Dhall.Util ( Censor , CheckFailed (..) , Header (..)+ , Input (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed ) -import qualified Control.Exception import qualified Data.Text.IO import qualified Data.Text.Prettyprint.Doc as Pretty import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal@@ -40,19 +45,21 @@ data Format = Format { chosenCharacterSet :: Maybe CharacterSet , censor :: Censor- , input :: PossiblyTransitiveInput+ , transitivity :: Transitivity+ , inputs :: NonEmpty Input , outputMode :: OutputMode } -- | Implementation of the @dhall format@ subcommand format :: Format -> IO ()-format (Format { input = input0, ..}) = go input0+format (Format { inputs = inputs0, transitivity = transitivity0, ..}) =+ handleMultipleChecksFailed "format" "formatted" go inputs0 where go input = do let directory = case input of- NonTransitiveStandardInput ->+ StandardInput -> "."- PossiblyTransitiveInputFile file _ ->+ InputFile file -> System.FilePath.takeDirectory file let status = Dhall.Import.emptyStatus directory@@ -65,26 +72,26 @@ <> Dhall.Pretty.prettyCharacterSet characterSet expr <> "\n") - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Data.Text.IO.readFile file - return (text, transitivity)-- NonTransitiveStandardInput -> do+ return (file, text, transitivity0)+ StandardInput -> do text <- Data.Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) - headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText + headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText+ case transitivity of Transitive -> for_ parsedExpression $ \import_ -> do maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return ()@@ -94,16 +101,16 @@ let formattedText = Pretty.Text.renderStrict docStream case outputMode of- Write ->+ Write -> do case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == formattedText then return () else AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy docStream) - NonTransitiveStandardInput -> do+ StandardInput -> do supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout Pretty.Terminal.renderIO@@ -112,12 +119,10 @@ then (fmap annToAnsiStyle docStream) else (Pretty.unAnnotateS docStream)) - Check ->- if originalText == formattedText- then return ()- else do- let command = "format"-- let modified = "formatted"+ return (Right ()) - Control.Exception.throwIO CheckFailed{..}+ Check ->+ return $+ if originalText == formattedText+ then Right ()+ else Left CheckFailed{..}
src/Dhall/Freeze.hs view
@@ -22,6 +22,7 @@ ) where import Data.Foldable (for_)+import Data.List.NonEmpty (NonEmpty) import Data.Maybe (fromMaybe) import Dhall.Pretty (CharacterSet, detectCharacterSet) import Dhall.Syntax@@ -34,9 +35,10 @@ ( Censor , CheckFailed (..) , Header (..)+ , Input (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed ) import System.Console.ANSI (hSupportsANSI) @@ -140,7 +142,8 @@ -- | Implementation of the @dhall freeze@ subcommand freeze :: OutputMode- -> PossiblyTransitiveInput+ -> Transitivity+ -> NonEmpty Input -> Scope -> Intent -> Maybe CharacterSet@@ -152,35 +155,37 @@ freezeWithManager :: IO Dhall.Import.Manager -> OutputMode- -> PossiblyTransitiveInput+ -> Transitivity+ -> NonEmpty Input -> Scope -> Intent -> Maybe CharacterSet -> Censor -> IO ()-freezeWithManager newManager outputMode input0 scope intent chosenCharacterSet censor = go input0+freezeWithManager newManager outputMode transitivity0 inputs scope intent chosenCharacterSet censor =+ handleMultipleChecksFailed "freeze" "frozen" go inputs where go input = do let directory = case input of- NonTransitiveStandardInput ->+ StandardInput -> "."- PossiblyTransitiveInputFile file _ ->+ InputFile file -> System.FilePath.takeDirectory file let status = Dhall.Import.emptyStatusWithManager newManager directory - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Text.IO.readFile file - return (text, transitivity)+ return (file, text, transitivity0) - NonTransitiveStandardInput -> do+ StandardInput -> do text <- Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) - (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor originalText+ (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet @@ -190,7 +195,7 @@ maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return ()@@ -210,7 +215,7 @@ let unAnnotated = Pretty.unAnnotateS stream case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == modifiedText then return () else@@ -218,7 +223,7 @@ file (Pretty.Text.renderLazy unAnnotated) - NonTransitiveStandardInput -> do+ StandardInput -> do supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout if supportsANSI then@@ -226,15 +231,13 @@ else Pretty.renderIO System.IO.stdout unAnnotated - Check ->- if originalText == modifiedText- then return ()- else do- let command = "freeze"-- let modified = "frozen"+ return (Right ()) - Exception.throwIO CheckFailed{..}+ Check ->+ return $+ if originalText == modifiedText+ then Right ()+ else Left CheckFailed{..} {-| Slightly more pure version of the `freeze` function
src/Dhall/Import.hs view
@@ -167,7 +167,6 @@ import Data.Text (Text) import Data.Typeable (Typeable) import Data.Void (Void, absurd)-import Dhall.Binary (StandardVersion (..)) import Dhall.Syntax ( Chunks (..)@@ -200,7 +199,6 @@ ) import Lens.Family.State.Strict (zoom) -import qualified Codec.CBOR.Encoding as Encoding import qualified Codec.CBOR.Write as Write import qualified Codec.Serialise import qualified Control.Monad.State.Strict as State@@ -566,22 +564,27 @@ Nothing -> fetch where fetch = do- ImportSemantics { importSemantics } <- loadImportWithSemisemanticCache import_+ ImportSemantics{ importSemantics } <- loadImportWithSemisemanticCache import_ - let variants = map (\version -> encodeExpression version (Core.alphaNormalize importSemantics))- [ minBound .. maxBound ]- case Data.Foldable.find ((== semanticHash). Dhall.Crypto.sha256Hash) variants of- Just bytes -> zoom cacheWarning (writeToSemanticCache semanticHash bytes)- Nothing -> do- let expectedHash = semanticHash- Status { _stack } <- State.get- let actualHash = hashExpression (Core.alphaNormalize importSemantics)- throwMissingImport (Imported _stack (HashMismatch {..}))+ let bytes = encodeExpression (Core.alphaNormalize importSemantics) - return (ImportSemantics {..})+ let actualHash = Dhall.Crypto.sha256Hash bytes + let expectedHash = semanticHash + if actualHash == expectedHash+ then do+ zoom cacheWarning (writeToSemanticCache semanticHash bytes) + else do+ Status{ _stack } <- State.get++ throwMissingImport (Imported _stack HashMismatch{..})++ return ImportSemantics{..}+++ -- Fetch encoded normal form from "semantic cache" fetchFromSemanticCache :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)@@ -600,7 +603,8 @@ -- with the old behavior State.evalStateT (writeToSemanticCache hash bytes) CacheWarned where- bytes = encodeExpression NoVersion expression+ bytes = encodeExpression expression+ hash = Dhall.Crypto.sha256Hash bytes writeToSemanticCache@@ -682,7 +686,7 @@ let betaNormal = Core.normalizeWith _normalizer substitutedExpr - let bytes = encodeExpression NoVersion betaNormal+ let bytes = encodeExpression betaNormal zoom cacheWarning (writeToSemisemanticCache semisemanticHash bytes) @@ -1206,33 +1210,19 @@ (loadWith expression) (emptyStatusWithManager newManager rootDirectory) { _semanticCacheMode = semanticCacheMode } -encodeExpression- :: StandardVersion- -- ^ `NoVersion` means to encode without the version tag- -> Expr Void Void- -> Data.ByteString.ByteString-encodeExpression _standardVersion expression = bytesStrict+encodeExpression :: Expr Void Void -> Data.ByteString.ByteString+encodeExpression expression = bytesStrict where intermediateExpression :: Expr Void Import intermediateExpression = fmap absurd expression - encoding =- case _standardVersion of- NoVersion ->- Codec.Serialise.encode intermediateExpression- s ->- Encoding.encodeListLen 2- <> Encoding.encodeString v- <> Codec.Serialise.encode intermediateExpression- where- v = Dhall.Binary.renderStandardVersion s+ encoding = Codec.Serialise.encode intermediateExpression bytesStrict = Write.toStrictByteString encoding -- | Hash a fully resolved expression hashExpression :: Expr Void Void -> Dhall.Crypto.SHA256Digest-hashExpression expression =- Dhall.Crypto.sha256Hash (encodeExpression NoVersion expression)+hashExpression = Dhall.Crypto.sha256Hash . encodeExpression {-| Convenience utility to hash a fully resolved expression and return the base-16 encoded hash with the @sha256:@ prefix
src/Dhall/Main.hs view
@@ -23,9 +23,10 @@ import Control.Applicative (optional, (<|>)) import Control.Exception (Handler (..), SomeException)+import Control.Monad (when) import Data.Foldable (for_) import Data.Maybe (fromMaybe)-import Data.List.NonEmpty (NonEmpty (..))+import Data.List.NonEmpty (NonEmpty (..), nonEmpty) import Data.Text (Text) import Data.Text.Prettyprint.Doc (Doc, Pretty) import Data.Void (Void)@@ -65,8 +66,8 @@ , Input (..) , Output (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed ) import qualified Codec.CBOR.JSON@@ -143,11 +144,11 @@ } | Normalize { file :: Input , alpha :: Bool } | Repl- | Format { possiblyTransitiveInput :: PossiblyTransitiveInput, outputMode :: OutputMode }- | Freeze { possiblyTransitiveInput :: PossiblyTransitiveInput, all_ :: Bool, cache :: Bool, outputMode :: OutputMode }+ | Format { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }+ | Freeze { deprecatedInPlace :: Bool, transitivity :: Transitivity, all_ :: Bool, cache :: Bool, outputMode :: OutputMode, inputs :: NonEmpty Input } | Hash { file :: Input, cache :: Bool } | Diff { expr1 :: Text, expr2 :: Text }- | Lint { possiblyTransitiveInput :: PossiblyTransitiveInput, outputMode :: OutputMode }+ | Lint { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input } | Tags { input :: Input , output :: Output@@ -242,17 +243,17 @@ Manipulate "format" "Standard code formatter for the Dhall language"- (Format <$> parseInplaceTransitive <*> parseCheck "formatted")+ (Format <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "formatted" <*> parseFiles) <|> subcommand Manipulate "freeze" "Add integrity checks to remote import statements of an expression"- (Freeze <$> parseInplaceTransitive <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen")+ (Freeze <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen" <*> parseFiles) <|> subcommand Manipulate "lint" "Improve Dhall code by using newer language features and removing dead code"- (Lint <$> parseInplaceTransitive <*> parseCheck "linted")+ (Lint <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "linted" <*> parseFiles) <|> subcommand Manipulate "rewrite-with-schemas"@@ -332,6 +333,12 @@ <*> parseVersion ) where+ deprecatedInPlace =+ Options.Applicative.switch+ ( Options.Applicative.long "inplace"+ <> Options.Applicative.internal -- completely hidden from help+ )+ argument = fmap Data.Text.pack . Options.Applicative.strArgument@@ -349,6 +356,21 @@ <> Options.Applicative.action "file" ) + parseFiles = fmap f (Options.Applicative.many p)+ where+ -- Parse explicit stdin in the input filepaths+ parseStdin inputs+ | any (== InputFile "-") inputs = StandardInput : filter (/= InputFile "-") inputs+ | otherwise = inputs++ f = fromMaybe (pure StandardInput) . nonEmpty . parseStdin . fmap InputFile++ p = Options.Applicative.strArgument+ ( Options.Applicative.help "Read expression from files instead of standard input"+ <> Options.Applicative.metavar "FILES"+ <> Options.Applicative.action "file"+ )+ parseOutput = fmap f (optional p) where f Nothing = StandardOutput@@ -422,22 +444,15 @@ <> Options.Applicative.action "file" ) + parseTransitiveSwitch = Options.Applicative.flag NonTransitive Transitive+ ( Options.Applicative.long "transitive"+ <> Options.Applicative.help "Modify the input and its transitive relative imports in-place"+ )+ parseInplaceNonTransitive = fmap InputFile parseInplace <|> pure StandardInput - parseInplaceTransitive =- fmap (\f -> PossiblyTransitiveInputFile f NonTransitive) parseInplace- <|> fmap (\f -> PossiblyTransitiveInputFile f Transitive) parseTransitive- <|> pure NonTransitiveStandardInput- where- parseTransitive = Options.Applicative.strOption- ( Options.Applicative.long "transitive"- <> Options.Applicative.help "Modify the specified file and its transitive relative imports in-place"- <> Options.Applicative.metavar "FILE"- <> Options.Applicative.action "file"- )- parseInput = fmap f (optional p) where f Nothing = StandardInput@@ -787,16 +802,21 @@ then return () else Exit.exitFailure - Format {..} ->- Dhall.Format.format- Dhall.Format.Format{ input = possiblyTransitiveInput, ..}+ Format {..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated" + Dhall.Format.format Dhall.Format.Format{..}+ Freeze {..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"+ let scope = if all_ then AllImports else OnlyRemoteImports let intent = if cache then Cache else Secure - Dhall.Freeze.freeze outputMode possiblyTransitiveInput scope intent chosenCharacterSet censor+ Dhall.Freeze.freeze outputMode transitivity inputs scope intent chosenCharacterSet censor Hash {..} -> do expression <- getExpression file@@ -815,27 +835,31 @@ Data.Text.IO.putStrLn (Dhall.Import.hashExpressionToCode normalizedExpression) - Lint { possiblyTransitiveInput = input0, ..} -> go input0+ Lint { transitivity = transitivity0, ..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"++ handleMultipleChecksFailed "lint" "linted" go inputs where go input = do let directory = case input of- NonTransitiveStandardInput -> "."- PossiblyTransitiveInputFile file _ -> System.FilePath.takeDirectory file+ StandardInput -> "."+ InputFile file -> System.FilePath.takeDirectory file let status = Dhall.Import.emptyStatus directory - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Data.Text.IO.readFile file - return (text, transitivity)- NonTransitiveStandardInput -> do+ return (file, text, transitivity0)+ StandardInput -> do text <- Data.Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) (Header header, parsedExpression) <-- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText+ Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet @@ -845,7 +869,7 @@ maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return ()@@ -860,23 +884,23 @@ let modifiedText = Pretty.Text.renderStrict stream <> "\n" case outputMode of- Write ->+ Write -> do case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == modifiedText then return () else writeDocToFile file doc - NonTransitiveStandardInput ->+ StandardInput -> renderDoc System.IO.stdout doc - Check ->- if originalText == modifiedText- then return ()- else do- let modified = "linted"+ return (Right ()) - Control.Exception.throwIO CheckFailed{ command = "lint", ..}+ Check ->+ return $+ if originalText == modifiedText+ then Right ()+ else Left CheckFailed{..} Encode {..} -> do expression <- getExpression file
+ src/Dhall/Marshal/Decode.hs view
@@ -0,0 +1,1492 @@+{-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Decode+ ( -- * General+ Decoder (..)+ , FromDhall(..)+ , Interpret+ , auto++ -- * Building decoders+ -- ** Simple decoders+ , bool+ , unit+ , void+ -- ** Numbers+ , natural+ , word+ , word8+ , word16+ , word32+ , word64+ , integer+ , int+ , int8+ , int16+ , int32+ , int64+ , scientific+ , double+ -- ** Textual+ , string+ , lazyText+ , strictText+ -- ** Containers+ , maybe+ , pair+ , sequence+ , list+ , vector+ , setFromDistinctList+ , setIgnoringDuplicates+ , hashSetFromDistinctList+ , hashSetIgnoringDuplicates+ , Dhall.Marshal.Decode.map+ , hashMap+ , pairFromMapEntry+ -- ** Functions+ , function+ , functionWith+ -- ** Records+ , RecordDecoder(..)+ , record+ , field+ -- ** Unions+ , UnionDecoder(..)+ , union+ , constructor++ -- * Generic decoding+ , GenericFromDhall(..)+ , GenericFromDhallUnion(..)+ , genericAuto+ , genericAutoWith++ -- * Decoding errors+ , DhallErrors(..)+ , showDhallErrors+ , InvalidDecoder(..)+ -- ** Extraction errors+ , ExtractErrors+ , ExtractError(..)+ , Extractor+ , typeError+ , extractError+ , MonadicExtractor+ , toMonadic+ , fromMonadic+ -- ** Typing errors+ , ExpectedTypeErrors+ , ExpectedTypeError(..)+ , Expector++ -- * Miscellaneous+ , InputNormalizer(..)+ , defaultInputNormalizer+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions+ , Result++ -- * Re-exports+ , Natural+ , Seq+ , Text+ , Vector+ , Generic+ ) where+++import Control.Applicative (empty, liftA2)+import Control.Exception (Exception)+import Control.Monad (guard)+import Control.Monad.Trans.State.Strict+import Data.Coerce (coerce)+import Data.Either.Validation+ ( Validation (..)+ , eitherToValidation+ , validationToEither+ )+import Data.Hashable (Hashable)+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Text.Prettyprint.Doc (Pretty)+import Data.Typeable (Proxy (..), Typeable)+import Dhall.Parser (Src (..))+import Dhall.Syntax+ ( Chunks (..)+ , DhallDouble (..)+ , Expr (..)+ , FunctionBinding (..)+ , Var (..)+ )+import GHC.Generics+import Prelude hiding (maybe, sequence)++import qualified Control.Applicative+import qualified Data.Foldable+import qualified Data.Functor.Compose+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet+import qualified Data.List as List+import qualified Data.List.NonEmpty+import qualified Data.Map+import qualified Data.Maybe+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Vector+import qualified Dhall.Core as Core+import qualified Dhall.Map+import qualified Dhall.Util++import Dhall.Marshal.Encode+import Dhall.Marshal.Internal++-- $setup+-- >>> import Dhall (input)++{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall+ into Haskell.++ You can produce `Decoder`s either explicitly:++> example :: Decoder (Vector Text)+> example = vector text++ ... or implicitly using `auto`:++> example :: Decoder (Vector Text)+> example = auto++ You can consume `Decoder`s using the `Dhall.input` function:++> input :: Decoder a -> Text -> IO a+-}+data Decoder a = Decoder+ { extract :: Expr Src Void -> Extractor Src Void a+ -- ^ Extracts Haskell value from the Dhall expression+ , expected :: Expector (Expr Src Void)+ -- ^ Dhall type of the Haskell value+ }+ deriving (Functor)++{-| Any value that implements `FromDhall` can be automatically decoded based on+ the inferred return type of `Dhall.input`.++>>> input auto "[1, 2, 3]" :: IO (Vector Natural)+[1,2,3]+>>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)+fromList [("a",False),("b",True)]++ This class auto-generates a default implementation for types that+ implement `Generic`. This does not auto-generate an instance for recursive+ types.++ The default instance can be tweaked using 'genericAutoWith' and custom+ 'InterpretOptions', or using+ [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+ and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class FromDhall a where+ autoWith :: InputNormalizer -> Decoder a+ default autoWith+ :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a+ autoWith _ = genericAuto++-- | A compatibility alias for `FromDhall`.+type Interpret = FromDhall+{-# DEPRECATED Interpret "Use FromDhall instead" #-}++{-| Use the default input normalizer for interpreting an input.++> auto = autoWith defaultInputNormalizer+-}+auto :: FromDhall a => Decoder a+auto = autoWith defaultInputNormalizer++++instance FromDhall Void where+ autoWith _ = void++instance FromDhall () where+ autoWith _ = unit++instance FromDhall Bool where+ autoWith _ = bool++instance FromDhall Natural where+ autoWith _ = natural++instance FromDhall Word where+ autoWith _ = word++instance FromDhall Word8 where+ autoWith _ = word8++instance FromDhall Word16 where+ autoWith _ = word16++instance FromDhall Word32 where+ autoWith _ = word32++instance FromDhall Word64 where+ autoWith _ = word64++instance FromDhall Integer where+ autoWith _ = integer++instance FromDhall Int where+ autoWith _ = int++instance FromDhall Int8 where+ autoWith _ = int8++instance FromDhall Int16 where+ autoWith _ = int16++instance FromDhall Int32 where+ autoWith _ = int32++instance FromDhall Int64 where+ autoWith _ = int64++instance FromDhall Scientific where+ autoWith _ = scientific++instance FromDhall Double where+ autoWith _ = double++instance {-# OVERLAPS #-} FromDhall [Char] where+ autoWith _ = string++instance FromDhall Data.Text.Lazy.Text where+ autoWith _ = lazyText++instance FromDhall Text where+ autoWith _ = strictText++instance FromDhall a => FromDhall (Maybe a) where+ autoWith opts = maybe (autoWith opts)++instance FromDhall a => FromDhall (Seq a) where+ autoWith opts = sequence (autoWith opts)++instance FromDhall a => FromDhall [a] where+ autoWith opts = list (autoWith opts)++instance FromDhall a => FromDhall (Vector a) where+ autoWith opts = vector (autoWith opts)++{-| Note that this instance will throw errors in the presence of duplicates in+ the list. To ignore duplicates, use `setIgnoringDuplicates`.+-}+instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where+ autoWith opts = setFromDistinctList (autoWith opts)++{-| Note that this instance will throw errors in the presence of duplicates in+ the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.+-}+instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where+ autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)++instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where+ autoWith inputNormalizer = Dhall.Marshal.Decode.map (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where+ autoWith inputNormalizer = Dhall.Marshal.Decode.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where+ autoWith inputNormalizer =+ functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)++instance (FromDhall a, FromDhall b) => FromDhall (a, b)++instance FromDhall (f (Result f)) => FromDhall (Result f) where+ autoWith inputNormalizer = Decoder {..}+ where+ extract (App _ expr) =+ fmap Result (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)+ extract expr = typeError expected expr++ expected = pure "result"++-- | You can use this instance to marshal recursive types from Dhall to Haskell.+--+-- Here is an example use of this instance:+--+-- > {-# LANGUAGE DeriveAnyClass #-}+-- > {-# LANGUAGE DeriveFoldable #-}+-- > {-# LANGUAGE DeriveFunctor #-}+-- > {-# LANGUAGE DeriveTraversable #-}+-- > {-# LANGUAGE DeriveGeneric #-}+-- > {-# LANGUAGE KindSignatures #-}+-- > {-# LANGUAGE QuasiQuotes #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TypeFamilies #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- >+-- > import Data.Fix (Fix(..))+-- > import Data.Text (Text)+-- > import Dhall (FromDhall)+-- > import GHC.Generics (Generic)+-- > import Numeric.Natural (Natural)+-- >+-- > import qualified Data.Fix as Fix+-- > import qualified Data.Functor.Foldable as Foldable+-- > import qualified Data.Functor.Foldable.TH as TH+-- > import qualified Dhall+-- > import qualified NeatInterpolation+-- >+-- > data Expr+-- > = Lit Natural+-- > | Add Expr Expr+-- > | Mul Expr Expr+-- > deriving (Show)+-- >+-- > TH.makeBaseFunctor ''Expr+-- >+-- > deriving instance Generic (ExprF a)+-- > deriving instance FromDhall a => FromDhall (ExprF a)+-- >+-- > example :: Text+-- > example = [NeatInterpolation.text|+-- > \(Expr : Type)+-- > -> let ExprF =+-- > < LitF :+-- > Natural+-- > | AddF :+-- > { _1 : Expr, _2 : Expr }+-- > | MulF :+-- > { _1 : Expr, _2 : Expr }+-- > >+-- >+-- > in \(Fix : ExprF -> Expr)+-- > -> let Lit = \(x : Natural) -> Fix (ExprF.LitF x)+-- >+-- > let Add =+-- > \(x : Expr)+-- > -> \(y : Expr)+-- > -> Fix (ExprF.AddF { _1 = x, _2 = y })+-- >+-- > let Mul =+-- > \(x : Expr)+-- > -> \(y : Expr)+-- > -> Fix (ExprF.MulF { _1 = x, _2 = y })+-- >+-- > in Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))+-- > |]+-- >+-- > convert :: Fix ExprF -> Expr+-- > convert = Fix.foldFix Foldable.embed+-- >+-- > main :: IO ()+-- > main = do+-- > x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)+-- >+-- > print (convert x :: Expr)+instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where+ autoWith inputNormalizer = Decoder {..}+ where+ extract expr0 = extract0 expr0+ where+ die = typeError expected expr0++ extract0 (Lam _ (FunctionBinding { functionBindingVariable = x }) expr) =+ extract1 (rename x "result" expr)+ extract0 _ = die++ extract1 (Lam _ (FunctionBinding { functionBindingVariable = y }) expr) =+ extract2 (rename y "Make" expr)+ extract1 _ = die++ extract2 expr = fmap resultToFix (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)++ rename a b expr+ | a /= b = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)+ | otherwise = expr++ expected = (\x -> Pi mempty "result" (Const Core.Type) (Pi mempty "Make" (Pi mempty "_" x "result") "result"))+ <$> Dhall.Marshal.Decode.expected (autoWith inputNormalizer :: Decoder (f (Result f)))++resultToFix :: Functor f => Result f -> Fix f+resultToFix (Result x) = Fix (fmap resultToFix x)++++{-| This is the underlying class that powers the `FromDhall` class's support+ for automatically deriving a generic implementation.+-}+class GenericFromDhall t f where+ genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))++instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where+ genericAutoWithNormalizer p inputNormalizer options = do+ res <- genericAutoWithNormalizer p inputNormalizer options+ pure (fmap M1 res)++instance GenericFromDhall t V1 where+ genericAutoWithNormalizer _ _ _ = pure Decoder {..}+ where+ extract expr = typeError expected expr++ expected = pure $ Union mempty++instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where+ genericAutoWithNormalizer p inputNormalizer options =+ pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))++instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where+ genericAutoWithNormalizer p inputNormalizer options = do+ res <- genericAutoWithNormalizer p inputNormalizer options+ pure (fmap M1 res)++instance GenericFromDhall t U1 where+ genericAutoWithNormalizer _ _ _ = pure (Decoder {..})+ where+ extract _ = pure U1++ expected = pure expected'++ expected' = Record (Dhall.Map.fromList [])++instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where+ genericAutoWithNormalizer p inputNormalizer options = do+ Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options+ Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++ let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL+ let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++ let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)++ let extract expression =+ liftA2 (:*:) (extractL expression) (extractR expression)++ return (Decoder {..})++instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where+ genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+ let nR :: M1 S s (K1 i a) r+ nR = undefined++ nameR <- fmap fieldModifier (getSelName nR)++ Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options++ let Decoder extractR expectedR = autoWith inputNormalizer++ let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL++ let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of+ Just expressionR ->+ liftA2 (:*:)+ (extractL expression)+ (fmap (M1 . K1) (extractR expressionR))+ _ -> die+ _ -> die++ return (Decoder {..})++instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where+ genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+ let nL :: M1 S s (K1 i a) r+ nL = undefined++ nameL <- fmap fieldModifier (getSelName nL)++ let Decoder extractL expectedL = autoWith inputNormalizer++ Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++ let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++ let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+ Just expressionL ->+ liftA2 (:*:)+ (fmap (M1 . K1) (extractL expressionL))+ (extractR expression)+ _ -> die+ _ -> die++ return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+ let nL :: M1 S s1 (K1 i1 a1) r+ nL = undefined++ let nR :: M1 S s2 (K1 i2 a2) r+ nR = undefined++ nameL <- fmap fieldModifier (getSelName nL)+ nameR <- fmap fieldModifier (getSelName nR)++ let Decoder extractL expectedL = autoWith inputNormalizer+ let Decoder extractR expectedR = autoWith inputNormalizer++ let expected = do+ l <- Core.makeRecordField <$> expectedL+ r <- Core.makeRecordField <$> expectedR+ pure $ Record+ (Dhall.Map.fromList+ [ (nameL, l)+ , (nameR, r)+ ]+ )++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of+ Just (expressionL, expressionR) ->+ liftA2 (:*:)+ (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))+ (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))+ Nothing -> die+ _ -> die++ return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where+ genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+ let n :: M1 S s (K1 i a) r+ n = undefined++ name <- fmap fieldModifier (getSelName n)++ let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer++ let expected =+ case singletonConstructors of+ Bare ->+ expected'+ Smart | selName n == "" ->+ expected'+ _ ->+ Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'++ let extract0 expression = fmap (M1 . K1) (extract' expression)++ let extract1 expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of+ Just subExpression ->+ fmap (M1 . K1) (extract' subExpression)+ Nothing ->+ die+ _ -> die++ let extract =+ case singletonConstructors of+ Bare -> extract0+ Smart | selName n == "" -> extract0+ _ -> extract1++ return (Decoder {..})++{-| `genericAuto` is the default implementation for `auto` if you derive+ `FromDhall`. The difference is that you can use `genericAuto` without+ having to explicitly provide a `FromDhall` instance for a type as long as+ the type derives `Generic`.+-}+genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a+genericAuto = genericAutoWith defaultInterpretOptions++{-| `genericAutoWith` is a configurable version of `genericAuto`.+-}+genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a+genericAutoWith options = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p defaultInputNormalizer options) 1))+ where+ withProxy :: (Proxy a -> Decoder a) -> Decoder a+ withProxy f = f Proxy++extractUnionConstructor+ :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))+extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =+ return (fld, e, Dhall.Map.delete fld kts)+extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =+ return (fld, RecordLit mempty, Dhall.Map.delete fld kts)+extractUnionConstructor _ =+ empty++{-| This is the underlying class that powers the `FromDhall` class's support+ for automatically deriving a generic implementation for a union type.+-}+class GenericFromDhallUnion t f where+ genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)++instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where+ genericUnionAutoWithNormalizer p inputNormalizer options =+ (<>)+ (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)+ (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)++instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where+ genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =+ constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)+ where+ n :: M1 C c1 f1 a+ n = undefined++ name = constructorModifier (Data.Text.pack (conName n))++++{-| Decode a `Prelude.Bool`.++>>> input bool "True"+True+-}+bool :: Decoder Bool+bool = Decoder {..}+ where+ extract (BoolLit b) = pure b+ extract expr = typeError expected expr++ expected = pure Bool++{-| Decode a `Prelude.Natural`.++>>> input natural "42"+42+-}+natural :: Decoder Natural+natural = Decoder {..}+ where+ extract (NaturalLit n) = pure n+ extract expr = typeError expected expr++ expected = pure Natural++{-| Decode an `Prelude.Integer`.++>>> input integer "+42"+42+-}+integer :: Decoder Integer+integer = Decoder {..}+ where+ extract (IntegerLit n) = pure n+ extract expr = typeError expected expr++ expected = pure Integer++wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+wordHelper name = Decoder {..}+ where+ extract (NaturalLit n)+ | toInteger n <= toInteger (maxBound @a) =+ pure (fromIntegral n)+ | otherwise =+ extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+ extract expr =+ typeError expected expr++ expected = pure Natural++{-| Decode a `Word` from a Dhall @Natural@.++>>> input word "42"+42+-}+word :: Decoder Word+word = wordHelper "Word"++{-| Decode a `Word8` from a Dhall @Natural@.++>>> input word8 "42"+42+-}+word8 :: Decoder Word8+word8 = wordHelper "Word8"++{-| Decode a `Word16` from a Dhall @Natural@.++>>> input word16 "42"+42+-}+word16 :: Decoder Word16+word16 = wordHelper "Word16"++{-| Decode a `Word32` from a Dhall @Natural@.++>>> input word32 "42"+42+-}+word32 :: Decoder Word32+word32 = wordHelper "Word32"++{-| Decode a `Word64` from a Dhall @Natural@.++>>> input word64 "42"+42+-}+word64 :: Decoder Word64+word64 = wordHelper "Word64"++intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+intHelper name = Decoder {..}+ where+ extract (IntegerLit n)+ | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =+ pure (fromIntegral n)+ | otherwise =+ extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+ extract expr =+ typeError expected expr++ expected = pure Integer++{-| Decode an `Int` from a Dhall @Integer@.++>>> input int "-42"+-42+-}+int :: Decoder Int+int = intHelper "Int"++{-| Decode an `Int8` from a Dhall @Integer@.++>>> input int8 "-42"+-42+-}+int8 :: Decoder Int8+int8 = intHelper "Int8"++{-| Decode an `Int16` from a Dhall @Integer@.++>>> input int16 "-42"+-42+-}+int16 :: Decoder Int16+int16 = intHelper "Int16"++{-| Decode an `Int32` from a Dhall @Integer@.++>>> input int32 "-42"+-42+-}+int32 :: Decoder Int32+int32 = intHelper "Int32"++{-| Decode an `Int64` from a Dhall @Integer@.++>>> input int64 "-42"+-42+-}+int64 :: Decoder Int64+int64 = intHelper "Int64"++{-| Decode a `Scientific`.++>>> input scientific "1e100"+1.0e100+-}+scientific :: Decoder Scientific+scientific = fmap Data.Scientific.fromFloatDigits double++{-| Decode a `Prelude.Double`.++>>> input double "42.0"+42.0+-}+double :: Decoder Double+double = Decoder {..}+ where+ extract (DoubleLit (DhallDouble n)) = pure n+ extract expr = typeError expected expr++ expected = pure Double++{-| Decode lazy `Data.Text.Text`.++>>> input lazyText "\"Test\""+"Test"+-}+lazyText :: Decoder Data.Text.Lazy.Text+lazyText = fmap Data.Text.Lazy.fromStrict strictText++{-| Decode strict `Data.Text.Text`.++>>> input strictText "\"Test\""+"Test"+-}+strictText :: Decoder Text+strictText = Decoder {..}+ where+ extract (TextLit (Chunks [] t)) = pure t+ extract expr = typeError expected expr++ expected = pure Text++{-| Decode a `Maybe`.++>>> input (maybe natural) "Some 1"+Just 1+-}+maybe :: Decoder a -> Decoder (Maybe a)+maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (Some e ) = fmap Just (extractIn e)+ extractOut (App None _) = pure Nothing+ extractOut expr = typeError expectedOut expr++ expectedOut = App Optional <$> expectedIn++{-| Decode a `Seq`.++>>> input (sequence natural) "[1, 2, 3]"+fromList [1,2,3]+-}+sequence :: Decoder a -> Decoder (Seq a)+sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (ListLit _ es) = traverse extractIn es+ extractOut expr = typeError expectedOut expr++ expectedOut = App List <$> expectedIn++{-| Decode a list.++>>> input (list natural) "[1, 2, 3]"+[1,2,3]+-}+list :: Decoder a -> Decoder [a]+list = fmap Data.Foldable.toList . sequence++{-| Decode a `Vector`.++>>> input (vector natural) "[1, 2, 3]"+[1,2,3]+-}+vector :: Decoder a -> Decoder (Vector a)+vector = fmap Data.Vector.fromList . list++{-| Decode a Dhall function into a Haskell function.++>>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+function+ :: Encoder a+ -> Decoder b+ -> Decoder (a -> b)+function = functionWith defaultInputNormalizer++{-| Decode a Dhall function into a Haskell function using the specified normalizer.++>>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+functionWith+ :: InputNormalizer+ -> Encoder a+ -> Decoder b+ -> Decoder (a -> b)+functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =+ Decoder extractOut expectedOut+ where+ normalizer_ = Just (getInputNormalizer inputNormalizer)++ extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of+ Success o -> o+ Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )++ expectedOut = Pi mempty "_" declared <$> expectedIn++{-| Decode a `Data.Set.Set` from a `List`.++>>> input (setIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (setIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)+setIgnoringDuplicates = fmap Data.Set.fromList . list++{-| Decode a `Data.HashSet.HashSet` from a `List`.++>>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+hashSetIgnoringDuplicates :: (Hashable a, Ord a)+ => Decoder a+ -> Decoder (Data.HashSet.HashSet a)+hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list++{-| Decode a `Data.Set.Set` from a `List` with distinct elements.++>>> input (setFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (setFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)+setFromDistinctList = setHelper Data.Set.size Data.Set.fromList++{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements.++>>> input (hashSetFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+hashSetFromDistinctList :: (Hashable a, Ord a, Show a)+ => Decoder a+ -> Decoder (Data.HashSet.HashSet a)+hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList+++setHelper :: (Eq a, Foldable t, Show a)+ => (t a -> Int)+ -> ([a] -> t a)+ -> Decoder a+ -> Decoder (t a)+setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (ListLit _ es) = case traverse extractIn es of+ Success vSeq+ | sameSize -> Success vSet+ | otherwise -> extractError err+ where+ vList = Data.Foldable.toList vSeq+ vSet = toSet vList+ sameSize = size vSet == Data.Sequence.length vSeq+ duplicates = vList List.\\ Data.Foldable.toList vSet+ err | length duplicates == 1 =+ "One duplicate element in the list: "+ <> (Data.Text.pack $ show $ head duplicates)+ | otherwise = Data.Text.pack $ unwords+ [ show $ length duplicates+ , "duplicates were found in the list, including"+ , show $ head duplicates+ ]+ Failure f -> Failure f+ extractOut expr = typeError expectedOut expr++ expectedOut = App List <$> expectedIn++{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"+fromList [("a",True),("b",False)]+>>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"+fromList [("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.map natural bool) expr+fromList [(1,False)]++-}+map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)+map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))++{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }")+[("a",True),("b",False)]+>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]")+[("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.hashMap natural bool) expr+fromList [(1,False)]++-}+hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)+hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))++{-| Decode a tuple from a @Prelude.Map.Entry@ record.++>>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"+("foo",3)+-}+pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)+pairFromMapEntry k v = Decoder extractOut expectedOut+ where+ extractOut (RecordLit kvs)+ | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs+ , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs+ = liftA2 (,) (extract k key) (extract v value)+ extractOut expr = typeError expectedOut expr++ expectedOut = do+ k' <- Core.makeRecordField <$> expected k+ v' <- Core.makeRecordField <$> expected v+ pure $ Record $ Dhall.Map.fromList+ [ ("mapKey", k')+ , ("mapValue", v')]++{-| Decode @()@ from an empty record.++>>> input unit "{=}" -- GHC doesn't print the result if it is ()++-}+unit :: Decoder ()+unit = Decoder {..}+ where+ extract (RecordLit fields)+ | Data.Foldable.null fields = pure ()+ extract expr = typeError expected expr++ expected = pure $ Record mempty++{-| Decode 'Void' from an empty union.++Since @<>@ is uninhabited, @'Dhall.input' 'void'@ will always fail.+-}+void :: Decoder Void+void = union mempty++{-| Decode a `String`++>>> input string "\"ABC\""+"ABC"++-}+string :: Decoder String+string = Data.Text.Lazy.unpack <$> lazyText++{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.++>>> input (pair natural bool) "{ _1 = 42, _2 = False }"+(42,False)+-}+pair :: Decoder a -> Decoder b -> Decoder (a, b)+pair l r = Decoder extractOut expectedOut+ where+ extractOut expr@(RecordLit fields) =+ (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)+ (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)+ <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)+ (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)+ extractOut expr = typeError expectedOut expr++ expectedOut = do+ l' <- Core.makeRecordField <$> expected l+ r' <- Core.makeRecordField <$> expected r+ pure $ Record $ Dhall.Map.fromList+ [ ("_1", l')+ , ("_2", r')]++++{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'+ from a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Project = Project+ { projectName :: Text+ , projectDescription :: Text+ , projectStars :: Natural+ }+:}++ And assume that we have the following Dhall record that we would like to+ parse as a @Project@:++> { name =+> "dhall-haskell"+> , description =+> "A configuration language guaranteed to terminate"+> , stars =+> 289+> }++ Our decoder has type 'Decoder' @Project@, but we can't build that out of any+ smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+ However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:++>>> :{+project :: Decoder Project+project =+ record+ ( Project <$> field "name" strictText+ <*> field "description" strictText+ <*> field "stars" natural+ )+:}+-}+newtype RecordDecoder a =+ RecordDecoder+ ( Data.Functor.Product.Product+ ( Control.Applicative.Const+ (Dhall.Map.Map Text (Expector (Expr Src Void)))+ )+ ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)+ )+ a+ )+ deriving (Functor, Applicative)++-- | Run a 'RecordDecoder' to build a 'Decoder'.+record :: RecordDecoder a -> Dhall.Marshal.Decode.Decoder a+record+ (RecordDecoder+ (Data.Functor.Product.Pair+ (Control.Applicative.Const fields)+ (Data.Functor.Compose.Compose extract)+ )+ ) = Decoder {..}+ where+ expected = Record <$> traverse (fmap Core.makeRecordField) fields++-- | Parse a single field of a record.+field :: Text -> Decoder a -> RecordDecoder a+field key (Decoder {..}) =+ RecordDecoder+ ( Data.Functor.Product.Pair+ ( Control.Applicative.Const+ (Dhall.Map.singleton key expected)+ )+ ( Data.Functor.Compose.Compose extractBody )+ )+ where+ extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of+ Just v -> extract v+ _ -> typeError expected expr+ extractBody expr = typeError expected expr++++{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union.++ For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+ | Result Text+ | Errored Text+:}++ And assume that we have the following Dhall union that we would like to+ parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++ Our decoder has type 'Decoder' @Status@, but we can't build that out of any+ smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+ However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:++>>> :{+status :: Decoder Status+status = union+ ( ( Queued <$> constructor "Queued" natural )+ <> ( Result <$> constructor "Result" strictText )+ <> ( Errored <$> constructor "Errored" strictText )+ )+:}++-}+newtype UnionDecoder a =+ UnionDecoder+ ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )+ deriving (Functor)++instance Semigroup (UnionDecoder a) where+ (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))++instance Monoid (UnionDecoder a) where+ mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))++-- | Run a 'UnionDecoder' to build a 'Decoder'.+union :: UnionDecoder a -> Decoder a+union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}+ where+ extract expr = case expected' of+ Failure e -> Failure $ fmap ExpectedTypeError e+ Success x -> extract' expr x++ extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.Marshal.Decode.extract) $ do+ (fld, e1, rest) <- extractUnionConstructor e0++ t <- Dhall.Map.lookup fld mp++ guard $+ Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')++ pure (t, e1)++ expected = Union <$> expected'++ expected' = traverse (fmap notEmptyRecord . Dhall.Marshal.Decode.expected) mp++-- | Parse a single constructor of a union.+constructor :: Text -> Decoder a -> UnionDecoder a+constructor key valueDecoder = UnionDecoder+ ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )++++{-| A newtype suitable for collecting one or more errors.+-}+newtype DhallErrors e = DhallErrors+ { getErrors :: NonEmpty e+ } deriving (Eq, Functor, Semigroup)++instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)++{-| Render a given prefix and some errors to a string.+-}+showDhallErrors :: Show e => String -> DhallErrors e -> String+showDhallErrors _ (DhallErrors (e :| [])) = show e+showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)+ where+ prefix =+ "Multiple errors were encountered" ++ ctx ++ ": \n\+ \ \n"++{-| One or more errors returned from extracting a Dhall expression to a+ Haskell expression.+-}+type ExtractErrors s a = DhallErrors (ExtractError s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where+ show = showDhallErrors " during extraction"++{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,+ as expressions are type-checked against the expected type before being passed to @extract@), or+ a term-level error, described with a freeform text value.+-}+data ExtractError s a =+ TypeMismatch (InvalidDecoder s a)+ | ExpectedTypeError ExpectedTypeError+ | ExtractError Text++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where+ show (TypeMismatch e) = show e+ show (ExpectedTypeError e) = show e+ show (ExtractError es) =+ _ERROR <> ": Failed extraction \n\+ \ \n\+ \The expression type-checked successfully but the transformation to the target \n\+ \type failed with the following error: \n\+ \ \n\+ \" <> Data.Text.unpack es <> "\n\+ \ \n"++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)++{-| Useful synonym for the `Validation` type used when marshalling Dhall+ expressions.+-}+type Extractor s a = Validation (ExtractErrors s a)++{-| Generate a type error during extraction by specifying the expected type+ and the actual type.+ The expected type is not yet determined.+-}+typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b+typeError expected actual = Failure $ case expected of+ Failure e -> fmap ExpectedTypeError e+ Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual++-- | Turn a `Data.Text.Text` message into an extraction failure.+extractError :: Text -> Extractor s a b+extractError = Failure . DhallErrors . pure . ExtractError++{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall+ code.+-}+type MonadicExtractor s a = Either (ExtractErrors s a)++-- | Switches from an @Applicative@ extraction result, able to accumulate errors,+-- to a @Monad@ extraction result, able to chain sequential operations.+toMonadic :: Extractor s a b -> MonadicExtractor s a b+toMonadic = validationToEither++-- | Switches from a @Monad@ extraction result, able to chain sequential errors,+-- to an @Applicative@ extraction result, able to accumulate errors.+fromMonadic :: MonadicExtractor s a b -> Extractor s a b+fromMonadic = eitherToValidation++{-| Every `Decoder` must obey the contract that if an expression's type matches+ the `expected` type then the `extract` function must not fail with a type+ error. However, decoding may still fail for other reasons (such as the+ decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate+ elements).++ This error type is used to indicate an internal error in the implementation+ of a `Decoder` where the expected type matched the Dhall expression, but the+ expression supplied to the extraction function did not match the expected+ type. If this happens that means that the `Decoder` itself needs to be+ fixed.+-}+data InvalidDecoder s a = InvalidDecoder+ { invalidDecoderExpected :: Expr s a+ , invalidDecoderExpression :: Expr s a+ }+ deriving (Typeable)++instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where+ show InvalidDecoder { .. } =+ _ERROR <> ": Invalid Dhall.Decoder \n\+ \ \n\+ \Every Decoder must provide an extract function that does not fail with a type \n\+ \error if an expression matches the expected type. You provided a Decoder that \n\+ \disobeys this contract \n\+ \ \n\+ \The Decoder provided has the expected dhall type: \n\+ \ \n\+ \" <> show txt0 <> "\n\+ \ \n\+ \and it threw a type error during extraction from the well-typed expression: \n\+ \ \n\+ \" <> show txt1 <> "\n\+ \ \n"+ where+ txt0 = Dhall.Util.insert invalidDecoderExpected+ txt1 = Dhall.Util.insert invalidDecoderExpression++{-| Useful synonym for the `Validation` type used when marshalling Dhall+ expressions.+-}+type Expector = Validation ExpectedTypeErrors++{-| One or more errors returned when determining the Dhall type of a+ Haskell expression.+-}+type ExpectedTypeErrors = DhallErrors ExpectedTypeError++{-| Error type used when determining the Dhall type of a Haskell expression.+-}+data ExpectedTypeError = RecursiveTypeError+ deriving (Eq, Show)++instance Exception ExpectedTypeError++instance Show ExpectedTypeErrors where+ show = showDhallErrors " while determining the expected type"++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"
+ src/Dhall/Marshal/Encode.hs view
@@ -0,0 +1,931 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Encode+ ( -- * General+ Encoder(..)+ , ToDhall(..)+ , Inject+ , inject++ -- * Building encoders++ -- ** Records+ , RecordEncoder(..)+ , recordEncoder+ , encodeField+ , encodeFieldWith+ -- ** Unions+ , UnionEncoder(..)+ , unionEncoder+ , encodeConstructor+ , encodeConstructorWith+ , (>|<)++ -- * Generic encoding+ , GenericToDhall(..)+ , genericToDhall+ , genericToDhallWith+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions++ -- * Miscellaneous+ , InputNormalizer(..)+ , defaultInputNormalizer+ , Result+ , (>$<)+ , (>*<)++ -- * Re-exports+ , Natural+ , Seq+ , Text+ , Vector+ , Generic+ ) where++import Control.Monad.Trans.State.Strict+import Data.Functor.Contravariant (Contravariant (..), Op (..), (>$<))+import Data.Functor.Contravariant.Divisible (Divisible (..), divided)+import Dhall.Parser (Src (..))+import Dhall.Syntax+ ( Chunks (..)+ , DhallDouble (..)+ , Expr (..)+ )+import GHC.Generics+import Prelude hiding (maybe, sequence)++import qualified Control.Applicative+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet+import qualified Data.Map+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Vector+import qualified Data.Void+import qualified Dhall.Core as Core+import qualified Dhall.Map++import Dhall.Marshal.Internal++-- $setup+-- >>> :set -XRecordWildCards+-- >>> import Dhall.Pretty.Internal (prettyExpr)++{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from+ Haskell into Dhall.+-}+data Encoder a = Encoder+ { embed :: a -> Expr Src Void+ -- ^ Embeds a Haskell value as a Dhall expression+ , declared :: Expr Src Void+ -- ^ Dhall type of the Haskell value+ }++instance Contravariant Encoder where+ contramap f (Encoder embed declared) = Encoder embed' declared+ where+ embed' x = embed (f x)++{-| This class is used by `Dhall.Marshal.Decode.FromDhall` instance for functions:++> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)++ You can convert Dhall functions with "simple" inputs (i.e. instances of this+ class) into Haskell functions. This works by:++ * Marshaling the input to the Haskell function into a Dhall expression (i.e.+ @x :: Expr Src Void@)+ * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input+ (i.e. @App f x@)+ * Normalizing the syntax tree (i.e. @normalize (App f x)@)+ * Marshaling the resulting Dhall expression back into a Haskell value++ This class auto-generates a default implementation for types that+ implement `Generic`. This does not auto-generate an instance for recursive+ types.++ The default instance can be tweaked using 'genericToDhallWith' and custom+ 'InterpretOptions', or using+ [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+ and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class ToDhall a where+ injectWith :: InputNormalizer -> Encoder a+ default injectWith+ :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a+ injectWith _ = genericToDhall++-- | A compatibility alias for `ToDhall`+type Inject = ToDhall+{-# DEPRECATED Inject "Use ToDhall instead" #-}++{-| Use the default input normalizer for injecting a value.++> inject = injectWith defaultInputNormalizer+-}+inject :: ToDhall a => Encoder a+inject = injectWith defaultInputNormalizer++++instance ToDhall Void where+ injectWith _ = Encoder {..}+ where+ embed = Data.Void.absurd++ declared = Union mempty++instance ToDhall Bool where+ injectWith _ = Encoder {..}+ where+ embed = BoolLit++ declared = Bool++instance ToDhall Data.Text.Lazy.Text where+ injectWith _ = Encoder {..}+ where+ embed text =+ TextLit (Chunks [] (Data.Text.Lazy.toStrict text))++ declared = Text++instance ToDhall Text where+ injectWith _ = Encoder {..}+ where+ embed text = TextLit (Chunks [] text)++ declared = Text++instance {-# OVERLAPS #-} ToDhall String where+ injectWith inputNormalizer =+ contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)++instance ToDhall Natural where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit++ declared = Natural++instance ToDhall Integer where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit++ declared = Integer++instance ToDhall Int where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++{-| Encode a 'Word' to a Dhall @Natural@.++>>> embed inject (12 :: Word)+NaturalLit 12+-}+instance ToDhall Word where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word8' to a Dhall @Natural@.++>>> embed inject (12 :: Word8)+NaturalLit 12+-}+instance ToDhall Word8 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word16' to a Dhall @Natural@.++>>> embed inject (12 :: Word16)+NaturalLit 12+-}+instance ToDhall Word16 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word32' to a Dhall @Natural@.++>>> embed inject (12 :: Word32)+NaturalLit 12+-}+instance ToDhall Word32 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word64' to a Dhall @Natural@.++>>> embed inject (12 :: Word64)+NaturalLit 12+-}+instance ToDhall Word64 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++instance ToDhall Double where+ injectWith _ = Encoder {..}+ where+ embed = DoubleLit . DhallDouble++ declared = Double++instance ToDhall Scientific where+ injectWith inputNormalizer =+ contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)++instance ToDhall () where+ injectWith _ = Encoder {..}+ where+ embed = const (RecordLit mempty)++ declared = Record mempty++instance ToDhall a => ToDhall (Maybe a) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut (Just x ) = Some (embedIn x)+ embedOut Nothing = App None declaredIn++ Encoder embedIn declaredIn = injectWith inputNormalizer++ declaredOut = App Optional declaredIn++instance ToDhall a => ToDhall (Seq a) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut xs = ListLit listType (fmap embedIn xs)+ where+ listType+ | null xs = Just (App List declaredIn)+ | otherwise = Nothing++ declaredOut = App List declaredIn++ Encoder embedIn declaredIn = injectWith inputNormalizer++instance ToDhall a => ToDhall [a] where+ injectWith = fmap (contramap Data.Sequence.fromList) injectWith++instance ToDhall a => ToDhall (Vector a) where+ injectWith = fmap (contramap Data.Vector.toList) injectWith++{-| Note that the output list will be sorted.++>>> let x = Data.Set.fromList ["mom", "hi" :: Text]+>>> prettyExpr $ embed inject x+[ "hi", "mom" ]++-}+instance ToDhall a => ToDhall (Data.Set.Set a) where+ injectWith = fmap (contramap Data.Set.toAscList) injectWith++-- | Note that the output list may not be sorted+instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where+ injectWith = fmap (contramap Data.HashSet.toList) injectWith++instance (ToDhall a, ToDhall b) => ToDhall (a, b)++{-| Embed a `Data.Map` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut m = ListLit listType (mapEntries m)+ where+ listType+ | Data.Map.null m = Just declaredOut+ | otherwise = Nothing++ declaredOut = App List (Record $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField declaredK)+ , ("mapValue", Core.makeRecordField declaredV)+ ])++ mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList+ recordPair (k, v) = RecordLit $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField $ embedK k)+ , ("mapValue", Core.makeRecordField $ embedV v)+ ]++ Encoder embedK declaredK = injectWith inputNormalizer+ Encoder embedV declaredV = injectWith inputNormalizer++{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut m = ListLit listType (mapEntries m)+ where+ listType+ | HashMap.null m = Just declaredOut+ | otherwise = Nothing++ declaredOut = App List (Record $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField declaredK)+ , ("mapValue", Core.makeRecordField declaredV)+ ])++ mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList+ recordPair (k, v) = RecordLit $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField $ embedK k)+ , ("mapValue", Core.makeRecordField $ embedV v)+ ]++ Encoder embedK declaredK = injectWith inputNormalizer+ Encoder embedV declaredV = injectWith inputNormalizer++instance ToDhall (f (Result f)) => ToDhall (Result f) where+ injectWith inputNormalizer = Encoder {..}+ where+ embed = App "Make" . Dhall.Marshal.Encode.embed (injectWith inputNormalizer) . _unResult+ declared = "result"++instance forall f. (Functor f, ToDhall (f (Result f))) => ToDhall (Fix f) where+ injectWith inputNormalizer = Encoder {..}+ where+ embed fixf =+ Lam Nothing (Core.makeFunctionBinding "result" (Const Core.Type)) $+ Lam Nothing (Core.makeFunctionBinding "Make" makeType) $+ embed' . fixToResult $ fixf++ declared = Pi Nothing "result" (Const Core.Type) $ Pi Nothing "_" makeType "result"++ makeType = Pi Nothing "_" declared' "result"+ Encoder embed' _ = injectWith @(Dhall.Marshal.Internal.Result f) inputNormalizer+ Encoder _ declared' = injectWith @(f (Dhall.Marshal.Internal.Result f)) inputNormalizer++fixToResult :: Functor f => Fix f -> Result f+fixToResult (Fix x) = Result (fmap fixToResult x)++++{-| This is the underlying class that powers the `Dhall.Marshal.Decode.FromDhall` class's support+ for automatically deriving a generic implementation.+-}+class GenericToDhall f where+ genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))++instance GenericToDhall f => GenericToDhall (M1 D d f) where+ genericToDhallWithNormalizer inputNormalizer options = do+ res <- genericToDhallWithNormalizer inputNormalizer options+ pure (contramap unM1 res)++instance GenericToDhall f => GenericToDhall (M1 C c f) where+ genericToDhallWithNormalizer inputNormalizer options = do+ res <- genericToDhallWithNormalizer inputNormalizer options+ pure (contramap unM1 res)++instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where+ genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+ let Encoder { embed = embed', declared = declared' } =+ injectWith inputNormalizer++ let n :: M1 S s (K1 i a) r+ n = undefined++ name <- fieldModifier <$> getSelName n++ let embed0 (M1 (K1 x)) = embed' x++ let embed1 (M1 (K1 x)) =+ RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))++ let embed =+ case singletonConstructors of+ Bare -> embed0+ Smart | selName n == "" -> embed0+ _ -> embed1++ let declared =+ case singletonConstructors of+ Bare ->+ declared'+ Smart | selName n == "" ->+ declared'+ _ ->+ Record (Dhall.Map.singleton name $ Core.makeRecordField declared')++ return (Encoder {..})++instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 (M1 l)) =+ case notEmptyRecordLit (embedL l) of+ Nothing ->+ Field declared $ Core.makeFieldSelection keyL+ Just valL ->+ App (Field declared $ Core.makeFieldSelection keyL) valL++ embed (R1 (M1 r)) =+ case notEmptyRecordLit (embedR r) of+ Nothing ->+ Field declared $ Core.makeFieldSelection keyR+ Just valR ->+ App (Field declared $ Core.makeFieldSelection keyR) valR++ declared =+ Union+ (Dhall.Map.fromList+ [ (keyL, notEmptyRecord declaredL)+ , (keyR, notEmptyRecord declaredR)+ ]+ )++ nL :: M1 i c1 f1 a+ nL = undefined++ nR :: M1 i c2 f2 a+ nR = undefined++ keyL = constructorModifier (Data.Text.pack (conName nL))+ keyR = constructorModifier (Data.Text.pack (conName nR))++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 l) =+ case maybeValL of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ where+ (keyL, maybeValL) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+ embed (R1 (M1 r)) =+ case notEmptyRecordLit (embedR r) of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR++ nR :: M1 i c h a+ nR = undefined++ keyR = constructorModifier (Data.Text.pack (conName nR))++ declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL++instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 (M1 l)) =+ case notEmptyRecordLit (embedL l) of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ embed (R1 r) =+ case maybeValR of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+ where+ (keyR, maybeValR) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++ nL :: M1 i c f a+ nL = undefined++ keyL = constructorModifier (Data.Text.pack (conName nL))++ declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where+ genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})+ where+ embed (L1 l) =+ case maybeValL of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ where+ (keyL, maybeValL) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+ embed (R1 r) =+ case maybeValR of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+ where+ (keyR, maybeValR) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++ declared = Union (Dhall.Map.union ktsL ktsR)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL+ ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where+ genericToDhallWithNormalizer inputNormalizer options = do+ Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options+ Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++ let embed (l :*: r) =+ RecordLit (Dhall.Map.union mapL mapR)+ where+ mapL =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++ mapR =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++ let declared = Record (Dhall.Map.union mapL mapR)+ where+ mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL+ mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++ pure (Encoder {..})++instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where+ genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+ let nR :: M1 S s (K1 i a) r+ nR = undefined++ nameR <- fmap fieldModifier (getSelName nR)++ Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options++ let Encoder embedR declaredR = injectWith inputNormalizer++ let embed (l :*: M1 (K1 r)) =+ RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)+ where+ mapL =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++ let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)+ where+ mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL++ return (Encoder {..})++instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where+ genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+ let nL :: M1 S s (K1 i a) r+ nL = undefined++ nameL <- fmap fieldModifier (getSelName nL)++ let Encoder embedL declaredL = injectWith inputNormalizer++ Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++ let embed (M1 (K1 l) :*: r) =+ RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)+ where+ mapR =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++ let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)+ where+ mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++ return (Encoder {..})++instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+ let nL :: M1 S s1 (K1 i1 a1) r+ nL = undefined++ let nR :: M1 S s2 (K1 i2 a2) r+ nR = undefined++ nameL <- fmap fieldModifier (getSelName nL)+ nameR <- fmap fieldModifier (getSelName nR)++ let Encoder embedL declaredL = injectWith inputNormalizer+ let Encoder embedR declaredR = injectWith inputNormalizer++ let embed (M1 (K1 l) :*: M1 (K1 r)) =+ RecordLit $+ Dhall.Map.fromList+ [ (nameL, Core.makeRecordField $ embedL l)+ , (nameR, Core.makeRecordField $ embedR r) ]+++ let declared =+ Record $ Dhall.Map.fromList+ [ (nameL, Core.makeRecordField declaredL)+ , (nameR, Core.makeRecordField declaredR) ]+++ return (Encoder {..})++instance GenericToDhall U1 where+ genericToDhallWithNormalizer _ _ = pure (Encoder {..})+ where+ embed _ = RecordLit mempty++ declared = Record mempty++{-| Use the default options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhall+ :: (Generic a, GenericToDhall (Rep a)) => Encoder a+genericToDhall+ = genericToDhallWith defaultInterpretOptions++{-| Use custom options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhallWith+ :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a+genericToDhallWith options+ = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer defaultInputNormalizer options) 1)++++{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build+ an 'Encoder' for a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Project = Project+ { projectName :: Text+ , projectDescription :: Text+ , projectStars :: Natural+ }+:}++ And assume that we have the following Dhall record that we would like to+ parse as a @Project@:++> { name =+> "dhall-haskell"+> , description =+> "A configuration language guaranteed to terminate"+> , stars =+> 289+> }++ Our encoder has type 'Encoder' @Project@, but we can't build that out of any+ smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).+ However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:++>>> :{+injectProject :: Encoder Project+injectProject =+ recordEncoder+ ( adapt >$< encodeFieldWith "name" inject+ >*< encodeFieldWith "description" inject+ >*< encodeFieldWith "stars" inject+ )+ where+ adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++ Or, since we are simply using the `ToDhall` instance to inject each field, we could write++>>> :{+injectProject :: Encoder Project+injectProject =+ recordEncoder+ ( adapt >$< encodeField "name"+ >*< encodeField "description"+ >*< encodeField "stars"+ )+ where+ adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++-}+newtype RecordEncoder a+ = RecordEncoder (Dhall.Map.Map Text (Encoder a))++instance Contravariant RecordEncoder where+ contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord++instance Divisible RecordEncoder where+ divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =+ RecordEncoder+ $ Dhall.Map.union+ ((contramap $ fst . f) <$> bEncoderRecord)+ ((contramap $ snd . f) <$> cEncoderRecord)+ conquer = RecordEncoder mempty++-- | Convert a `RecordEncoder` into the equivalent `Encoder`.+recordEncoder :: RecordEncoder a -> Encoder a+recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType+ where+ recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord+ makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord++{-| Specify how to encode one field of a record using the default `ToDhall`+ instance for that type.+-}+encodeField :: ToDhall a => Text -> RecordEncoder a+encodeField name = encodeFieldWith name inject++{-| Specify how to encode one field of a record by supplying an explicit+ `Encoder` for that field.+-}+encodeFieldWith :: Text -> Encoder a -> RecordEncoder a+encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType++++{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+ | Result Text+ | Errored Text+:}++ And assume that we have the following Dhall union that we would like to+ parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++ Our encoder has type 'Encoder' @Status@, but we can't build that out of any+ smaller encoders, as 'Encoder's cannot be combined.+ However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+ ( encodeConstructorWith "Queued" inject+ >|< encodeConstructorWith "Result" inject+ >|< encodeConstructorWith "Errored" inject+ )+ where+ adapt (Queued n) = Left n+ adapt (Result t) = Right (Left t)+ adapt (Errored e) = Right (Right e)+:}++ Or, since we are simply using the `ToDhall` instance to inject each branch, we could write++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+ ( encodeConstructor "Queued"+ >|< encodeConstructor "Result"+ >|< encodeConstructor "Errored"+ )+ where+ adapt (Queued n) = Left n+ adapt (Result t) = Right (Left t)+ adapt (Errored e) = Right (Right e)+:}++-}+newtype UnionEncoder a =+ UnionEncoder+ ( Data.Functor.Product.Product+ ( Control.Applicative.Const+ ( Dhall.Map.Map+ Text+ ( Expr Src Void )+ )+ )+ ( Op (Text, Expr Src Void) )+ a+ )+ deriving (Contravariant)++-- | Convert a `UnionEncoder` into the equivalent `Encoder`.+unionEncoder :: UnionEncoder a -> Encoder a+unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =+ Encoder+ { embed = \x ->+ let (name, y) = embedF x+ in case notEmptyRecordLit y of+ Nothing -> Field (Union fields') $ Core.makeFieldSelection name+ Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val+ , declared =+ Union fields'+ }+ where+ fields' = fmap notEmptyRecord fields++{-| Specify how to encode an alternative by using the default `ToDhall` instance+ for that type.+-}+encodeConstructor+ :: ToDhall a+ => Text+ -> UnionEncoder a+encodeConstructor name = encodeConstructorWith name inject++{-| Specify how to encode an alternative by providing an explicit `Encoder`+ for that alternative.+-}+encodeConstructorWith+ :: Text+ -> Encoder a+ -> UnionEncoder a+encodeConstructorWith name encodeType = UnionEncoder $+ Data.Functor.Product.Pair+ ( Control.Applicative.Const+ ( Dhall.Map.singleton+ name+ ( declared encodeType )+ )+ )+ ( Op ( (name,) . embed encodeType )+ )++-- | Combines two 'UnionEncoder' values. See 'UnionEncoder' for usage+-- notes.+--+-- Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';+-- however, this allows 'UnionEncoder' to not need a 'Divisible' instance+-- itself (since no instance is possible).+(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)+UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))+ >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =+ UnionEncoder+ ( Data.Functor.Product.Pair+ ( Control.Applicative.Const (mx <> my) )+ ( Op (either fx fy) )+ )++infixr 5 >|<++++-- | Infix 'divided'+(>*<) :: Divisible f => f a -> f b -> f (a, b)+(>*<) = divided++infixr 5 >*<
+ src/Dhall/Marshal/Internal.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Internal+ ( InputNormalizer(..)+ , defaultInputNormalizer+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions++ -- * Miscellaneous+ , Result(..)++ -- * Helpers for the generic deriving machinery+ , getSelName+ , notEmptyRecord+ , notEmptyRecordLit+ , unsafeExpectRecord+ , unsafeExpectRecordLit+ , unsafeExpectUnion+ , unsafeExpectUnionLit++ -- * Re-exports+ , Fix(..)+ , HashMap+ , Map+ , Natural+ , Scientific+ , Seq+ , Text+ , Vector+ , Void+ , Word8+ , Word16+ , Word32+ , Word64+ , Generic+ ) where++import Control.Monad.Trans.State.Strict+import Data.Fix (Fix (..))+import Data.HashMap.Strict (HashMap)+import Data.Map (Map)+import Data.Scientific (Scientific)+import Data.Sequence (Seq)+import Data.Text (Text)+import Data.Vector (Vector)+import Data.Void (Void)+import Data.Word (Word16, Word32, Word64, Word8)+import Dhall.Parser (Src (..))+import Dhall.Syntax (Expr (..), RecordField (..))+import GHC.Generics+import Numeric.Natural (Natural)+import Prelude hiding (maybe, sequence)++import qualified Data.Text+import qualified Dhall.Core as Core+import qualified Dhall.Map++{-| This type is exactly the same as `Data.Fix.Fix` except with a different+ `Dhall.Marshal.Decode.FromDhall` instance. This intermediate type+ simplifies the implementation of the inner loop for the+ `Dhall.Marshal.Decode.FromDhall` instance for `Fix`.+-}+newtype Result f = Result { _unResult :: f (Result f) }++{-| Use these options to tweak how Dhall derives a generic implementation of+ `Dhall.Marshal.Decode.FromDhall`.+-}+data InterpretOptions = InterpretOptions+ { fieldModifier :: Text -> Text+ -- ^ Function used to transform Haskell field names into their corresponding+ -- Dhall field names+ , constructorModifier :: Text -> Text+ -- ^ Function used to transform Haskell constructor names into their+ -- corresponding Dhall alternative names+ , singletonConstructors :: SingletonConstructors+ -- ^ Specify how to handle constructors with only one field. The default is+ -- `Smart`+ }++{-| This is only used by the `Dhall.Marshal.Decode.FromDhall` instance for+ functions in order to normalize the function input before marshaling the+ input into a Dhall expression.+-}+newtype InputNormalizer = InputNormalizer+ { getInputNormalizer :: Core.ReifiedNormalizer Void }++-- | Default normalization-related settings (no custom normalization)+defaultInputNormalizer :: InputNormalizer+defaultInputNormalizer = InputNormalizer+ { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }++{-| This type specifies how to model a Haskell constructor with 1 field in+ Dhall++ For example, consider the following Haskell datatype definition:++ > data Example = Foo { x :: Double } | Bar Double++ Depending on which option you pick, the corresponding Dhall type could be:++ > < Foo : Double | Bar : Double > -- Bare++ > < Foo : { x : Double } | Bar : { _1 : Double } > -- Wrapped++ > < Foo : { x : Double } | Bar : Double > -- Smart+-}+data SingletonConstructors+ = Bare+ -- ^ Never wrap the field in a record+ | Wrapped+ -- ^ Always wrap the field in a record+ | Smart+ -- ^ Only fields in a record if they are named++{-| Default interpret options for generics-based instances,+ which you can tweak or override, like this:++> genericAutoWith+> (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })+-}+defaultInterpretOptions :: InterpretOptions+defaultInterpretOptions = InterpretOptions+ { fieldModifier =+ id+ , constructorModifier =+ id+ , singletonConstructors =+ Smart+ }++unsafeExpectUnion+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))+unsafeExpectUnion _ (Union kts) =+ kts+unsafeExpectUnion name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecord+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecord _ (Record kts) =+ kts+unsafeExpectRecord name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectUnionLit+ :: Text+ -> Expr Src Void+ -> (Text, Maybe (Expr Src Void))+unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =+ (k, Nothing)+unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =+ (k, Just v)+unsafeExpectUnionLit name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecordLit+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecordLit _ (RecordLit kvs) =+ kvs+unsafeExpectRecordLit name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)+notEmptyRecordLit e = case e of+ RecordLit m | null m -> Nothing+ _ -> Just e++notEmptyRecord :: Expr s a -> Maybe (Expr s a)+notEmptyRecord e = case e of+ Record m | null m -> Nothing+ _ -> Just e++getSelName :: Selector s => M1 i s f a -> State Int Text+getSelName n = case selName n of+ "" -> do i <- get+ put (i + 1)+ pure (Data.Text.pack ("_" ++ show i))+ nn -> pure (Data.Text.pack nn)
src/Dhall/Normalize.hs view
@@ -668,11 +668,11 @@ t' <- loop t pure (Assert t')- Equivalent l r -> do+ Equivalent cs l r -> do l' <- loop l r' <- loop r - pure (Equivalent l' r')+ pure (Equivalent cs l' r') With e ks v -> do e' <- loop e v' <- loop v@@ -917,7 +917,7 @@ Record _ -> False _ -> loop e' Assert t -> loop t- Equivalent l r -> loop l && loop r+ Equivalent _ l r -> loop l && loop r With{} -> False Note _ e' -> loop e' ImportAlt _ _ -> False
src/Dhall/Parser/Expression.hs view
@@ -10,7 +10,6 @@ import Control.Applicative (Alternative (..), liftA2, optional) import Data.ByteArray.Encoding (Base (..)) import Data.Foldable (foldl')-import Data.Functor (void) import Data.List.NonEmpty (NonEmpty (..)) import Data.Text (Text) import Dhall.Src (Src (..))@@ -113,8 +112,18 @@ parsers :: forall a. Parser a -> Parsers a parsers embedded = Parsers {..} where- completeExpression_ = whitespace *> expression <* whitespace+ completeExpression_ =+ many shebang *> whitespace *> expression <* whitespace + shebang = do+ _ <- text "#!"++ let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++ _ <- Dhall.Parser.Combinators.takeWhile predicate++ endOfLine+ expression = noted ( choice@@ -341,7 +350,7 @@ operatorParsers :: [Parser (Expr s a -> Expr s a -> Expr s a)] operatorParsers =- [ Equivalent <$ _equivalent <* whitespace+ [ Equivalent . Just <$> _equivalent <* whitespace , ImportAlt <$ _importAlt <* nonemptyWhitespace , BoolOr <$ _or <* whitespace , NaturalPlus <$ _plus <* nonemptyWhitespace@@ -350,7 +359,7 @@ , BoolAnd <$ _and <* whitespace , (\cs -> Combine (Just cs) Nothing) <$> _combine <* whitespace , (\cs -> Prefer (Just cs) PreferFromSource) <$> _prefer <* whitespace- , (CombineTypes . Just) <$> _combineTypes <* whitespace+ , CombineTypes . Just <$> _combineTypes <* whitespace , NaturalTimes <$ _times <* whitespace -- Make sure that `==` is not actually the prefix of `===` , BoolEQ <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace@@ -718,7 +727,7 @@ , unescapedCharacterFast , unescapedCharacterSlow , tab- , endOfLine+ , endOfLine_ ] where escapeSingleQuotes = do@@ -757,7 +766,7 @@ where predicate c = c == '$' || c == '\'' - endOfLine = do+ endOfLine_ = do a <- "\n" <|> "\r\n" b <- singleQuoteContinue return (Chunks [] a <> b)@@ -769,12 +778,12 @@ singleQuoteLiteral = do _ <- text "''"+ _ <- endOfLine+ a <- singleQuoteContinue return (Dhall.Syntax.toDoubleQuoted a)- where- endOfLine = (void (char '\n') <|> void (text "\r\n")) <?> "newline" textLiteral = (do literal <- doubleQuotedLiteral <|> singleQuoteLiteral
src/Dhall/Parser/Token.hs view
@@ -4,6 +4,7 @@ -- | Parse Dhall tokens. Even though we don't have a tokenizer per-se this --- module is useful for keeping some small parsing utilities. module Dhall.Parser.Token (+ endOfLine, validCodepoint, whitespace, lineComment,@@ -135,6 +136,12 @@ import Numeric.Natural (Natural) +-- | Match an end-of-line character sequence+endOfLine :: Parser Text+endOfLine =+ ( Text.Parser.Char.text "\n" + <|> Text.Parser.Char.text "\r\n"+ ) <?> "newline" -- | Returns `True` if the given `Int` is a valid Unicode codepoint validCodepoint :: Int -> Bool@@ -360,14 +367,9 @@ commentText <- Dhall.Parser.Combinators.takeWhile predicate - endOfLine+ _ <- endOfLine return ("--" <> commentText)- where- endOfLine =- ( void (Text.Parser.Char.char '\n' )- <|> void (Text.Parser.Char.text "\r\n")- ) <?> "newline" -- | Parsed text doesn't include opening braces blockComment :: Parser Text@@ -396,8 +398,6 @@ where predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t' - endOfLine = (Text.Parser.Char.text "\r\n" <?> "newline")- blockCommentContinue :: Parser Text blockCommentContinue = endOfComment <|> continue where@@ -1207,8 +1207,10 @@ _at = reservedChar '@' <?> "\"@\"" -- | Parse the equivalence symbol (@===@ or @≡@)-_equivalent :: Parser ()-_equivalent = (void (char '≡' <?> "\"≡\"") <|> void (text "===")) <?> "operator"+_equivalent :: Parser CharacterSet+_equivalent =+ (Unicode <$ char '≡' <?> "\"≡\"")+ <|> (ASCII <$ text "===" <?> "===") -- | Parse the @missing@ keyword _missing :: Parser ()
src/Dhall/Pretty/Internal.hs view
@@ -153,6 +153,7 @@ Combine (Just Unicode) _ _ _ -> Unicode CombineTypes (Just Unicode) _ _ -> Unicode Prefer (Just Unicode) _ _ _ -> Unicode+ Equivalent (Just Unicode) _ _ -> Unicode _ -> mempty -- | Pretty print an expression@@ -927,10 +928,10 @@ spacer = if Text.length op == 1 then " " else " " prettyEquivalentExpression :: Pretty a => Expr Src a -> Doc Ann- prettyEquivalentExpression a0@(Equivalent _ _) =+ prettyEquivalentExpression a0@(Equivalent _ _ _) = prettyOperator (equivalent characterSet) (docs a0) where- docs (Equivalent a b) = prettyImportAltExpression b : docs a+ docs (Equivalent _ a b) = prettyImportAltExpression b : docs a docs a | Just doc <- preserveSource a = [ doc ]
src/Dhall/Schemas.hs view
@@ -27,7 +27,7 @@ import Dhall.Syntax (Expr (..), Import, Var (..)) import Dhall.Util ( Censor (..)- , CheckFailed (..)+ , MultipleCheckFailed (..) , Header (..) , Input (..) , OutputMode (..)@@ -68,11 +68,11 @@ -- | Implementation of the @dhall rewrite-with-schemas@ subcommand schemasCommand :: Schemas -> IO () schemasCommand Schemas{..} = do- originalText <- case input of- InputFile file -> Text.IO.readFile file- StandardInput -> Text.IO.getContents+ (inputName, originalText) <- case input of+ InputFile file -> (,) file <$> Text.IO.readFile file+ StandardInput -> (,) "(input)" <$> Text.IO.getContents - (Header header, expression) <- Util.getExpressionAndHeaderFromStdinText censor originalText+ (Header header, expression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText let characterSet = fromMaybe (detectCharacterSet expression) chosenCharacterSet @@ -115,7 +115,9 @@ let modified = "rewritten" - Exception.throwIO CheckFailed{..}+ let inputs = pure input++ Exception.throwIO MultipleCheckFailed{..} decodeSchema :: Expr s Void -> Maybe (Expr s Void, Map Text (Expr s Void)) decodeSchema (RecordLit m)
src/Dhall/Syntax.hs view
@@ -440,10 +440,10 @@ -- | > Var (V x 0) ~ x -- > Var (V x n) ~ x@n | Var Var- -- | > Lam (FunctionBinding _ "x" _ _ A) b ~ λ(x : A) -> b+ -- | > Lam _ (FunctionBinding _ "x" _ _ A) b ~ λ(x : A) -> b | Lam (Maybe CharacterSet) (FunctionBinding s a) (Expr s a)- -- | > Pi "_" A B ~ A -> B- -- > Pi x A B ~ ∀(x : A) -> B+ -- | > Pi _ "_" A B ~ A -> B+ -- > Pi _ x A B ~ ∀(x : A) -> B | Pi (Maybe CharacterSet) Text (Expr s a) (Expr s a) -- | > App f a ~ f a | App (Expr s a) (Expr s a)@@ -581,7 +581,7 @@ | RecordLit (Map Text (RecordField s a)) -- | > Union [(k1, Just t1), (k2, Nothing)] ~ < k1 : t1 | k2 > | Union (Map Text (Maybe (Expr s a)))- -- | > Combine Nothing x y ~ x ∧ y+ -- | > Combine _ Nothing x y ~ x ∧ y -- -- The first field is a `Just` when the `Combine` operator is introduced -- as a result of desugaring duplicate record fields:@@ -592,9 +592,9 @@ -- > (Combine (Just k) x y) -- > )] | Combine (Maybe CharacterSet) (Maybe Text) (Expr s a) (Expr s a)- -- | > CombineTypes x y ~ x ⩓ y+ -- | > CombineTypes _ x y ~ x ⩓ y | CombineTypes (Maybe CharacterSet) (Expr s a) (Expr s a)- -- | > Prefer False x y ~ x ⫽ y+ -- | > Prefer _ False x y ~ x ⫽ y -- -- The first field is a `True` when the `Prefer` operator is introduced as a -- result of desugaring a @with@ expression@@ -614,8 +614,8 @@ | Project (Expr s a) (Either [Text] (Expr s a)) -- | > Assert e ~ assert : e | Assert (Expr s a)- -- | > Equivalent x y ~ x ≡ y- | Equivalent (Expr s a) (Expr s a)+ -- | > Equivalent _ x y ~ x ≡ y+ | Equivalent (Maybe CharacterSet) (Expr s a) (Expr s a) -- | > With x y e ~ x with y = e | With (Expr s a) (NonEmpty Text) (Expr s a) -- | > Note s x ~ e@@ -842,7 +842,7 @@ unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b unsafeSubExpressions f (Assert a) = Assert <$> f a-unsafeSubExpressions f (Equivalent a b) = Equivalent <$> f a <*> f b+unsafeSubExpressions f (Equivalent cs a b) = Equivalent cs <$> f a <*> f b unsafeSubExpressions f (With a b c) = With <$> f a <*> pure b <*> f c unsafeSubExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r unsafeSubExpressions _ (Let {}) = unhandledConstructor "Let"@@ -1083,8 +1083,16 @@ pretty (ImportHashed Nothing p) = Pretty.pretty p pretty (ImportHashed (Just h) p) =- Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)+ Pretty.group (Pretty.flatAlt long short)+ where+ long =+ Pretty.align+ ( Pretty.pretty p <> Pretty.hardline+ <> " sha256:" <> Pretty.pretty (show h)+ ) + short = Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)+ -- | Reference to an external resource data Import = Import { importHashed :: ImportHashed@@ -1138,6 +1146,7 @@ Lam _ a b -> Lam Nothing (denoteFunctionBinding a) (denote b) Pi _ t a b -> Pi Nothing t (denote a) (denote b) Field a (FieldSelection _ b _) -> Field (denote a) (FieldSelection Nothing b Nothing)+ Equivalent _ a b -> Equivalent Nothing (denote a) (denote b) expression -> Lens.over unsafeSubExpressions denote expression where denoteRecordField (RecordField _ e _ _) = RecordField Nothing (denote e) Nothing Nothing
src/Dhall/TH.hs view
@@ -8,6 +8,7 @@ module Dhall.TH ( -- * Template Haskell staticDhallExpression+ , dhall , makeHaskellTypeFromUnion , makeHaskellTypes , HaskellType(..)@@ -18,7 +19,7 @@ import Dhall (FromDhall, ToDhall) import Dhall.Syntax (Expr (..)) import GHC.Generics (Generic)-import Language.Haskell.TH.Quote (dataToExpQ)+import Language.Haskell.TH.Quote (QuasiQuoter (..), dataToExpQ) import Language.Haskell.TH.Syntax ( Bang (..)@@ -82,6 +83,23 @@ -- A workaround for a problem in TemplateHaskell (see -- https://stackoverflow.com/questions/38143464/cant-find-inerface-file-declaration-for-variable) liftText = fmap (AppE (VarE 'Text.pack)) . Syntax.lift . Text.unpack++{-| A quasi-quoter for Dhall expressions.++ This quoter is build on top of 'staticDhallExpression'. Therefore consult the+ documentation of that function for further information.++ This quoter is meant to be used in expression context only; Other contexts+ like pattern contexts or declaration contexts are not supported and will+ result in an error.+-}+dhall :: QuasiQuoter+dhall = QuasiQuoter+ { quoteExp = staticDhallExpression . Text.pack+ , quotePat = const $ error "dhall quasi-quoter: Quoting patterns is not supported!"+ , quoteType = const $ error "dhall quasi-quoter: Quoting types is not supported!"+ , quoteDec = const $ error "dhall quasi-quoter: Quoting declarations is not supported!"+ } {-| Convert a Dhall type to a Haskell type that does not require any new data declarations beyond the data declarations supplied as the first
src/Dhall/Tutorial.hs view
@@ -1619,7 +1619,7 @@ -- > let replicate = https://prelude.dhall-lang.org/List/replicate -- > in replicate 5 -- > $--- > $ dhall freeze --inplace ./foo.dhall+-- > $ dhall freeze ./foo.dhall -- > $ cat ./foo.dhall -- > let replicate = -- > https://prelude.dhall-lang.org/List/replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347@@ -1744,10 +1744,9 @@ -- > (List (List Natural)) -- > (replicate 5 (List Natural) (replicate 5 Natural 1)) ----- You can also use the formatter to modify files in place using the--- @--inplace@ flag (i.e. for formatting source code):+-- You can also use the formatter to modify files in place: ----- > $ dhall format --inplace ./unformatted+-- > $ dhall format ./unformatted -- -- Carefully note that the code formatter does not preserve all comments. -- Currently, the formatter only preserves two types of comments:
src/Dhall/TypeCheck.hs view
@@ -1225,7 +1225,7 @@ _ -> die (NotAnEquivalence _T) - Equivalent x y -> do+ Equivalent _ x y -> do _A₀' <- loop ctx x let _A₀'' = quote names _A₀'
src/Dhall/Util.hs view
@@ -1,5 +1,7 @@+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeApplications #-} -- | Shared utility functions @@ -10,7 +12,6 @@ , _ERROR , Censor(..) , Input(..)- , PossiblyTransitiveInput(..) , Transitivity(..) , OutputMode(..) , Output(..)@@ -19,11 +20,16 @@ , getExpressionAndHeaderFromStdinText , Header(..) , CheckFailed(..)+ , MultipleCheckFailed(..)+ , handleMultipleChecksFailed ) where import Control.Exception (Exception (..)) import Control.Monad.IO.Class (MonadIO (..)) import Data.Bifunctor (first)+import Data.Either (lefts)+import Data.Foldable (toList)+import Data.List.NonEmpty (NonEmpty (..)) import Data.String (IsString) import Data.Text (Text) import Data.Text.Prettyprint.Doc (Doc, Pretty)@@ -112,13 +118,13 @@ case input of Input_ (InputFile file) -> Data.Text.IO.readFile file Input_ StandardInput -> Data.Text.IO.getContents- StdinText text -> pure text+ StdinText _ text -> pure text let name = case input of Input_ (InputFile file) -> file Input_ StandardInput -> "(input)"- StdinText _ -> "(input)"+ StdinText inputName _ -> inputName let result = parser name inText @@ -140,17 +146,14 @@ data Censor = NoCensor | Censor -- | Path to input-data Input = StandardInput | InputFile FilePath+data Input = StandardInput | InputFile FilePath deriving (Eq) -- | Path to input or raw input text, necessary since we can't read STDIN twice-data InputOrTextFromStdin = Input_ Input | StdinText Text--{-| For utilities that may want to process transitive dependencies, like- @dhall freeze@--}-data PossiblyTransitiveInput- = NonTransitiveStandardInput- | PossiblyTransitiveInputFile FilePath Transitivity+data InputOrTextFromStdin+ = Input_ Input+ | StdinText String Text+ -- ^ @StdinText name text@ where name is a user-friendly name describing the+ -- input expression, used in parsing error messages {-| Specifies whether or not an input's transitive dependencies should also be processed. Transitive dependencies are restricted to relative file imports.@@ -170,15 +173,25 @@ -} data OutputMode = Write | Check +-- | A check failure corresponding to a single input.+-- This type is intended to be used with 'MultipleCheckFailed' for error+-- reporting.+newtype CheckFailed = CheckFailed { input :: Input }+ -- | Exception thrown when the @--check@ flag to a command-line subcommand fails-data CheckFailed = CheckFailed { command :: Text, modified :: Text }+data MultipleCheckFailed = MultipleCheckFailed+ { command :: Text+ , modified :: Text+ , inputs :: NonEmpty Input+ } -instance Exception CheckFailed+instance Exception MultipleCheckFailed -instance Show CheckFailed where- show CheckFailed{..} =- _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed\n\- \\n\+instance Show MultipleCheckFailed where+ show MultipleCheckFailed{..} =+ _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed on:\n\+ \\n" <> files <>+ "\n\ \You ran ❰dhall " <> command_ <> " --check❱, but the input appears to have not\n\ \been " <> modified_ <> " before, or was changed since the last time the input\n\ \was " <> modified_ <> ".\n"@@ -187,6 +200,32 @@ command_ = Data.Text.unpack command + files = unlines . map format $ toList inputs++ format input = case input of+ StandardInput -> "↳ (stdin)"+ InputFile file -> "↳ " <> file++-- | Run IO for multiple inputs, then collate all the check failures before+-- throwing if there was any failure+handleMultipleChecksFailed+ :: (Foldable t, Traversable t)+ => Text+ -> Text+ -> (a -> IO (Either CheckFailed ()))+ -> t a+ -> IO ()+handleMultipleChecksFailed command modified f xs = post =<< mapM f xs+ where+ post results =+ case lefts (toList results) of+ [] -> pure ()+ cf:cfs -> Control.Exception.throwIO $ MultipleCheckFailed+ { command+ , modified+ , inputs = fmap input (cf:|cfs)+ }+ -- | Convenient utility for retrieving an expression getExpression :: Censor -> Input -> IO (Expr Src Import) getExpression censor = get Dhall.Parser.exprFromText censor . Input_@@ -199,6 +238,6 @@ -- | Convenient utility for retrieving an expression along with its header from -- | text already read from STDIN (so it's not re-read) getExpressionAndHeaderFromStdinText- :: Censor -> Text -> IO (Header, Expr Src Import)-getExpressionAndHeaderFromStdinText censor =- get Dhall.Parser.exprAndHeaderFromText censor . StdinText+ :: Censor -> String -> Text -> IO (Header, Expr Src Import)+getExpressionAndHeaderFromStdinText censor inputName =+ get Dhall.Parser.exprAndHeaderFromText censor . StdinText inputName
tests/Dhall/Test/Import.hs view
@@ -1,11 +1,10 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-} module Dhall.Test.Import where import Control.Exception (SomeException) import Data.Text (Text)-import Dhall.Import (MissingImports (..))-import Dhall.Parser (SourcedException (..)) import Prelude hiding (FilePath) import Test.Tasty (TestTree) import Turtle (FilePath, (</>))@@ -53,8 +52,17 @@ return path ) - failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest (Turtle.lstree (importDirectory </> "failure"))+ failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest (do+ path <- Turtle.lstree (importDirectory </> "failure") + let expectedSuccesses =+ [ importDirectory </> "failure/unit/DontRecoverCycle.dhall"+ , importDirectory </> "failure/unit/DontRecoverTypeError.dhall"+ ]++ Monad.guard (path `notElem` expectedSuccesses)+ return path )+ let testTree = Tasty.testGroup "import tests" [ successTests@@ -69,7 +77,13 @@ let directoryString = FilePath.takeDirectory pathString - let expectedFailures = []+ let expectedFailures =+ [ importDirectory </> "success/unit/cors/TwoHopsA.dhall"+ , importDirectory </> "success/unit/cors/SelfImportAbsoluteA.dhall"+ , importDirectory </> "success/unit/cors/AllowedAllA.dhall"+ , importDirectory </> "success/unit/cors/SelfImportRelativeA.dhall"+ , importDirectory </> "success/unit/cors/OnlyGithubA.dhall"+ ] Test.Util.testCase path expectedFailures (do @@ -79,10 +93,6 @@ let originalCache = "dhall-lang/tests/import/cache" - let setCache = Turtle.export "XDG_CACHE_HOME"-- let unsetCache = Turtle.unset "XDG_CACHE_HOME"- let httpManager = HTTP.newManager HTTP.tlsManagerSettings@@ -94,24 +104,43 @@ let usesCache = [ "hashFromCacheA.dhall" , "unit/asLocation/HashA.dhall"- , "unit/IgnorePoisonedCacheA.dhall"]+ , "unit/IgnorePoisonedCacheA.dhall"+ , "unit/DontCacheIfHashA.dhall"+ ] - let endsIn path' = not $ null $ Turtle.match (Turtle.ends path') path+ let endsIn path' =+ not (null (Turtle.match (Turtle.ends path') (Test.Util.toDhallPath path))) let buildNewCache = do- tempdir <- Turtle.mktempdir "/tmp" "dhall-cache"- Turtle.liftIO $ Turtle.cptree originalCache tempdir- return tempdir+ tempdir <- Turtle.mktempdir "/tmp" "dhall-cache"+ Turtle.liftIO (Turtle.cptree originalCache tempdir)+ return tempdir let runTest = if any endsIn usesCache then Turtle.runManaged $ do cacheDir <- buildNewCache- setCache $ Turtle.format Turtle.fp cacheDir++ let set = do+ m <- Turtle.need "XDG_CACHE_HOME"++ Turtle.export "XDG_CACHE_HOME" (Turtle.format Turtle.fp cacheDir)++ return m++ let reset Nothing = do+ Turtle.unset "XDG_CACHE_HOME"+ reset (Just x) = do+ Turtle.export "XDG_CACHE_HOME" x++ _ <- Turtle.managed (Exception.bracket set reset)+ _ <- Turtle.liftIO load- unsetCache++ return () else do _ <- load+ return () let handler :: SomeException -> IO ()@@ -130,8 +159,12 @@ actualExpr <- Core.throws (Parser.exprFromText mempty text) - Exception.catch+ succeeded <- Exception.catch @SomeException (do _ <- Test.Util.load actualExpr+ return True+ )+ (\_ -> return False) - fail "Import should have failed, but it succeeds")- (\(SourcedException _ (MissingImports _)) -> pure ()) )+ if succeeded+ then fail "Import should have failed, but it succeeds"+ else return () )
tests/format/ipfsB.dhall view
@@ -11,7 +11,8 @@ labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` } let k8s =- https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd+ https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall+ sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd let serviceName = "ipfs"
tests/format/issue1400-2B.dhall view
@@ -3,7 +3,8 @@ = λ(a : Type) → { field : Text , nesting :- ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ ./Nesting+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting , contents : a }
tests/format/sha256PrintingB.dhall view
@@ -1,4 +1,5 @@ let replicate =- https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c+ https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate+ sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c in replicate 5
tests/freeze/cachedB.dhall view
@@ -1,2 +1,3 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+ ./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70 ? ./True.dhall
tests/freeze/incorrectHashB.dhall view
@@ -1,2 +1,3 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+ ./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70 ? ./True.dhall
tests/freeze/protectedB.dhall view
@@ -1,2 +1,3 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+ ./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70 ? ./True.dhall
tests/freeze/unprotectedB.dhall view
@@ -1,2 +1,3 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+ ./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70 ? ./True.dhall