Add support for empty alternatives (#863)

... as standardized in https://github.com/dhall-lang/dhall-lang/pull/438

This also adds `dhall-json` support for empty alternatives

In particular, this translates empty alternatives to strings encoding the alternative name

```haskell
-- ./example.dhall

let Role = < Wizard | Fighter | Rogue >

in  [ Role.Wizard, Role.Fighter ]
```

```
$ dhall-to-json <<< './example.dhall'
["Wizard","Fighter"]
```
This commit is contained in:
Gabriel Gonzalez 2019-03-27 15:29:10 -07:00 committed by GitHub
parent bf067eeb69
commit a2ab6a59ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 480 additions and 381 deletions

View File

@ -272,7 +272,7 @@ dhallToJSON e0 = loop (Dhall.Core.normalize e0)
(Dhall.Core.TextLit
(Dhall.Core.Chunks [] nestedField)
)
[ ("Inline", Dhall.Core.Record []) ]
[ ("Inline", Just (Dhall.Core.Record [])) ]
)
] -> do
contents' <- loop contents
@ -303,7 +303,7 @@ dhallToJSON e0 = loop (Dhall.Core.normalize e0)
, Dhall.Core.UnionLit
"Inline"
(Dhall.Core.RecordLit [])
[ ("Nested", Dhall.Core.Text) ]
[ ("Nested", Just Dhall.Core.Text) ]
)
] -> do
let contents' =
@ -322,6 +322,8 @@ dhallToJSON e0 = loop (Dhall.Core.normalize e0)
a' <- traverse loop a
return (Data.Aeson.toJSON (Dhall.Map.toMap a'))
Dhall.Core.UnionLit _ b _ -> loop b
Dhall.Core.App (Dhall.Core.Field (Dhall.Core.Union _) _) b -> loop b
Dhall.Core.Field (Dhall.Core.Union _) k -> return (toJSON k)
_ -> Left (Unsupported e)
toOrderedList :: Ord k => Map k v -> [(k, v)]
@ -671,13 +673,13 @@ convertToHomogeneousMaps (Conversion {..}) e0 = loop (Dhall.Core.normalize e0)
Dhall.Core.Union a ->
Dhall.Core.Union a'
where
a' = fmap loop a
a' = fmap (fmap loop) a
Dhall.Core.UnionLit a b c ->
Dhall.Core.UnionLit a b' c'
where
b' = loop b
c' = fmap loop c
b' = loop b
c' = fmap (fmap loop) c
Dhall.Core.Combine a b ->
Dhall.Core.Combine a' b'

@ -1 +1 @@
Subproject commit b1c9e532e66dc1a5d60ddc9a84139212fb1f44a1
Subproject commit 9303e67aa71d28b2a95d93f7ef910f6e714069e6

View File

@ -909,7 +909,8 @@ instance GenericInterpret V1 where
expected = Union mempty
unsafeExpectUnion :: Text -> Expr Src X -> Dhall.Map.Map Text (Expr Src X)
unsafeExpectUnion
:: Text -> Expr Src X -> Dhall.Map.Map Text (Maybe (Expr Src X))
unsafeExpectUnion _ (Union kts) =
kts
unsafeExpectUnion name expression =
@ -924,7 +925,9 @@ unsafeExpectRecord name expression =
(name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)
unsafeExpectUnionLit
:: Text -> Expr Src X -> (Text, Expr Src X, Dhall.Map.Map Text (Expr Src X))
:: Text
-> Expr Src X
-> (Text, Expr Src X, Dhall.Map.Map Text (Maybe (Expr Src X)))
unsafeExpectUnionLit _ (UnionLit k v kts) =
(k, v, kts)
unsafeExpectUnionLit name expression =
@ -938,6 +941,11 @@ unsafeExpectRecordLit name expression =
Dhall.Core.internalError
(name <> ": Unexpected constructor: " <> Dhall.Core.pretty expression)
possible :: Expr s a -> Maybe (Expr s a)
possible e = case e of
RecordLit m | null m -> Nothing
_ -> Just e
instance (Constructor c1, Constructor c2, GenericInterpret f1, GenericInterpret f2) => GenericInterpret (M1 C c1 f1 :+: M1 C c2 f2) where
genericAutoWith options@(InterpretOptions {..}) = pure (Type {..})
where
@ -957,7 +965,10 @@ instance (Constructor c1, Constructor c2, GenericInterpret f1, GenericInterpret
extract _ = Nothing
expected =
Union (Dhall.Map.fromList [(nameL, expectedL), (nameR, expectedR)])
Union
(Dhall.Map.fromList
[(nameL, possible expectedL), (nameR, possible expectedR)]
)
Type extractL expectedL = evalState (genericAutoWith options) 1
Type extractR expectedR = evalState (genericAutoWith options) 1
@ -976,7 +987,7 @@ instance (Constructor c, GenericInterpret (f :+: g), GenericInterpret h) => Gene
extract _ = Nothing
expected =
Union (Dhall.Map.insert name expectedR ktsL)
Union (Dhall.Map.insert name (possible expectedR) ktsL)
Type extractL expectedL = evalState (genericAutoWith options) 1
Type extractR expectedR = evalState (genericAutoWith options) 1
@ -997,7 +1008,7 @@ instance (Constructor c, GenericInterpret f, GenericInterpret (g :+: h)) => Gene
extract _ = Nothing
expected =
Union (Dhall.Map.insert name expectedL ktsR)
Union (Dhall.Map.insert name (possible expectedL) ktsR)
Type extractL expectedL = evalState (genericAutoWith options) 1
Type extractR expectedR = evalState (genericAutoWith options) 1
@ -1248,13 +1259,22 @@ instance (Constructor c1, Constructor c2, GenericInject f1, GenericInject f2) =>
genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})
where
embed (L1 (M1 l)) =
UnionLit keyL (embedL l) (Dhall.Map.singleton keyR declaredR)
UnionLit
keyL
(embedL l)
(Dhall.Map.singleton keyR (possible declaredR))
embed (R1 (M1 r)) =
UnionLit keyR (embedR r) (Dhall.Map.singleton keyL declaredL)
UnionLit
keyR
(embedR r)
(Dhall.Map.singleton keyL (possible declaredL))
declared =
Union (Dhall.Map.fromList [(keyL, declaredL), (keyR, declaredR)])
Union
(Dhall.Map.fromList
[(keyL, possible declaredL), (keyR, possible declaredR)]
)
nL :: M1 i c1 f1 a
nL = undefined
@ -1272,7 +1292,10 @@ instance (Constructor c, GenericInject (f :+: g), GenericInject h) => GenericInj
genericInjectWith options@(InterpretOptions {..}) = pure (InputType {..})
where
embed (L1 l) =
UnionLit keyL valL (Dhall.Map.insert keyR declaredR ktsL')
UnionLit
keyL
valL
(Dhall.Map.insert keyR (possible declaredR) ktsL')
where
(keyL, valL, ktsL') =
unsafeExpectUnionLit "genericInjectWith (:+:)" (embedL l)
@ -1283,7 +1306,7 @@ instance (Constructor c, GenericInject (f :+: g), GenericInject h) => GenericInj
keyR = constructorModifier (Data.Text.pack (conName nR))
declared = Union (Dhall.Map.insert keyR declaredR ktsL)
declared = Union (Dhall.Map.insert keyR (possible declaredR) ktsL)
InputType embedL declaredL = evalState (genericInjectWith options) 1
InputType embedR declaredR = evalState (genericInjectWith options) 1
@ -1295,7 +1318,10 @@ instance (Constructor c, GenericInject f, GenericInject (g :+: h)) => GenericInj
where
embed (L1 (M1 l)) = UnionLit keyL (embedL l) ktsR
embed (R1 r) =
UnionLit keyR valR (Dhall.Map.insert keyL declaredL ktsR')
UnionLit
keyR
valR
(Dhall.Map.insert keyL (possible declaredL) ktsR')
where
(keyR, valR, ktsR') =
unsafeExpectUnionLit "genericInjectWith (:+:)" (embedR r)
@ -1305,7 +1331,7 @@ instance (Constructor c, GenericInject f, GenericInject (g :+: h)) => GenericInj
keyL = constructorModifier (Data.Text.pack (conName nL))
declared = Union (Dhall.Map.insert keyL declaredL ktsR)
declared = Union (Dhall.Map.insert keyL (possible declaredL) ktsR)
InputType embedL declaredL = evalState (genericInjectWith options) 1
InputType embedR declaredR = evalState (genericInjectWith options) 1
@ -1513,7 +1539,7 @@ union (UnionType (Data.Functor.Compose.Compose mp)) = Type
, expected = Union expect
}
where
expect = Dhall.expected <$> mp
expect = (possible . Dhall.expected) <$> mp
extractF e0 = do
UnionLit fld e1 rest <- Just e0
t <- Dhall.Map.lookup fld mp
@ -1689,10 +1715,12 @@ inputUnion ( UnionInputType ( Data.Functor.Product.Pair ( Control.Applicative.Co
InputType
{ embed = \x ->
let (name, y) = embedF x
in UnionLit name y (Dhall.Map.delete name fields)
in UnionLit name y (Dhall.Map.delete name fields')
, declared =
Union fields
Union fields'
}
where
fields' = fmap possible fields
inputConstructorWith
:: Text

View File

@ -341,9 +341,14 @@ encode (Union xTs₀) =
TList [ TInt 11, TMap xTs ]
where
xTs = do
(x, _T) <- Dhall.Map.toList (Dhall.Map.sort xTs)
(x, mT) <- Dhall.Map.toList (Dhall.Map.sort xTs)
let x = TString x
let _T = encode _T
let _T = case mT of
Nothing -> TNull
Just _T -> encode _T
return (x, _T)
encode (UnionLit x t yTs) =
TList [ TInt 12, TString x, t, TMap yTs ]
@ -351,9 +356,11 @@ encode (UnionLit x t₀ yTs₀) =
t = encode t
yTs = do
(y, _T) <- Dhall.Map.toList (Dhall.Map.sort yTs)
(y, mT) <- Dhall.Map.toList (Dhall.Map.sort yTs)
let y = TString y
let _T = encode _T
let _T = case mT of
Just _T -> encode _T
Nothing -> TNull
return (y, _T)
encode (BoolLit b) =
TBool b
@ -656,9 +663,11 @@ decodeMaybe (TList (TInt 10 : t₁ : xs₁)) = do
return (Project t (Dhall.Set.fromList xs))
decodeMaybe (TList [ TInt 11, TMap xTs ]) = do
let process (TString x, _T) = do
_T <- decodeMaybe _T
mT <- case _T of
TNull -> return Nothing
_ -> fmap Just (decodeMaybe _T)
return (x, _T)
return (x, mT)
process _ =
empty
@ -669,7 +678,9 @@ decodeMaybe (TList [ TInt 12, TString x, t₁, TMap yTs₁ ]) = do
t <- decodeMaybe t
let process (TString y, _T) = do
_T <- decodeMaybe _T
_T <- case _T of
TNull -> return Nothing
_ -> fmap Just (decodeMaybe _T)
return (y, _T)
process _ =

View File

@ -438,10 +438,10 @@ data Expr s a
| Record (Map Text (Expr s a))
-- | > RecordLit [(k1, v1), (k2, v2)] ~ { k1 = v1, k2 = v2 }
| RecordLit (Map Text (Expr s a))
-- | > Union [(k1, t1), (k2, t2)] ~ < k1 : t1 | k2 : t2 >
| Union (Map Text (Expr s a))
-- | > UnionLit k v [(k1, t1), (k2, t2)] ~ < k = v | k1 : t1 | k2 : t2 >
| UnionLit Text (Expr s a) (Map Text (Expr s a))
-- | > Union [(k1, Just t1), (k2, Nothing)] ~ < k1 : t1 | k2 >
| Union (Map Text (Maybe (Expr s a)))
-- | > UnionLit k v [(k1, Just t1), (k2, Nothing)] ~ < k = v | k1 : t1 | k2 >
| UnionLit Text (Expr s a) (Map Text (Maybe (Expr s a)))
-- | > Combine x y ~ x ∧ y
| Combine (Expr s a) (Expr s a)
-- | > CombineTypes x y ~ x ⩓ y
@ -522,8 +522,8 @@ instance Functor (Expr s) where
fmap _ OptionalBuild = OptionalBuild
fmap f (Record r) = Record (fmap (fmap f) r)
fmap f (RecordLit r) = RecordLit (fmap (fmap f) r)
fmap f (Union u) = Union (fmap (fmap f) u)
fmap f (UnionLit v e u) = UnionLit v (fmap f e) (fmap (fmap f) u)
fmap f (Union u) = Union (fmap (fmap (fmap f)) u)
fmap f (UnionLit v e u) = UnionLit v (fmap f e) (fmap (fmap (fmap f)) u)
fmap f (Combine e1 e2) = Combine (fmap f e1) (fmap f e2)
fmap f (CombineTypes e1 e2) = CombineTypes (fmap f e1) (fmap f e2)
fmap f (Prefer e1 e2) = Prefer (fmap f e1) (fmap f e2)
@ -599,8 +599,8 @@ instance Monad (Expr s) where
OptionalBuild >>= _ = OptionalBuild
Record a >>= k = Record (fmap (>>= k) a)
RecordLit a >>= k = RecordLit (fmap (>>= k) a)
Union a >>= k = Union (fmap (>>= k) a)
UnionLit a b c >>= k = UnionLit a (b >>= k) (fmap (>>= k) c)
Union a >>= k = Union (fmap (fmap (>>= k)) a)
UnionLit a b c >>= k = UnionLit a (b >>= k) (fmap (fmap (>>= k)) c)
Combine a b >>= k = Combine (a >>= k) (b >>= k)
CombineTypes a b >>= k = CombineTypes (a >>= k) (b >>= k)
Prefer a b >>= k = Prefer (a >>= k) (b >>= k)
@ -666,8 +666,8 @@ instance Bifunctor Expr where
first _ OptionalBuild = OptionalBuild
first k (Record a ) = Record (fmap (first k) a)
first k (RecordLit a ) = RecordLit (fmap (first k) a)
first k (Union a ) = Union (fmap (first k) a)
first k (UnionLit a b c ) = UnionLit a (first k b) (fmap (first k) c)
first k (Union a ) = Union (fmap (fmap (first k)) a)
first k (UnionLit a b c ) = UnionLit a (first k b) (fmap (fmap (first k)) c)
first k (Combine a b ) = Combine (first k a) (first k b)
first k (CombineTypes a b ) = CombineTypes (first k a) (first k b)
first k (Prefer a b ) = Prefer (first k a) (first k b)
@ -925,11 +925,11 @@ shift d v (RecordLit a) = RecordLit a'
a' = fmap (shift d v) a
shift d v (Union a) = Union a'
where
a' = fmap (shift d v) a
a' = fmap (fmap (shift d v)) a
shift d v (UnionLit a b c) = UnionLit a b' c'
where
b' = shift d v b
c' = fmap (shift d v) c
b' = shift d v b
c' = fmap (fmap (shift d v)) c
shift d v (Combine a b) = Combine a' b'
where
a' = shift d v a
@ -1095,10 +1095,19 @@ subst x e (Some a) = Some a'
subst _ _ None = None
subst _ _ OptionalFold = OptionalFold
subst _ _ OptionalBuild = OptionalBuild
subst x e (Record kts) = Record (fmap (subst x e) kts)
subst x e (RecordLit kvs) = RecordLit (fmap (subst x e) kvs)
subst x e (Union kts) = Union (fmap (subst x e) kts)
subst x e (UnionLit a b kts) = UnionLit a (subst x e b) (fmap (subst x e) kts)
subst x e (Record kts) = Record kts'
where
kts' = fmap (subst x e) kts
subst x e (RecordLit kvs) = RecordLit kvs'
where
kvs' = fmap (subst x e) kvs
subst x e (Union kts) = Union kts'
where
kts' = fmap (fmap (subst x e)) kts
subst x e (UnionLit a b kts) = UnionLit a b' kts'
where
b' = subst x e b
kts' = fmap (fmap (subst x e)) kts
subst x e (Combine a b) = Combine a' b'
where
a' = subst x e a
@ -1381,13 +1390,13 @@ alphaNormalize (RecordLit kvs₀) =
alphaNormalize (Union kts) =
Union kts
where
kts = fmap alphaNormalize kts
kts = fmap (fmap alphaNormalize) kts
alphaNormalize (UnionLit k v kts) =
UnionLit k v kts
where
v = alphaNormalize v
kts = fmap alphaNormalize kts
kts = fmap (fmap alphaNormalize) kts
alphaNormalize (Combine l r) =
Combine l r
where
@ -1465,7 +1474,7 @@ boundedType Text = True
boundedType (App List _) = False
boundedType (App Optional t) = boundedType t
boundedType (Record kvs) = all boundedType kvs
boundedType (Union kvs) = all boundedType kvs
boundedType (Union kvs) = all (all boundedType) kvs
boundedType _ = False
-- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)
@ -1527,8 +1536,8 @@ denote OptionalFold = OptionalFold
denote OptionalBuild = OptionalBuild
denote (Record a ) = Record (fmap denote a)
denote (RecordLit a ) = RecordLit (fmap denote a)
denote (Union a ) = Union (fmap denote a)
denote (UnionLit a b c ) = UnionLit a (denote b) (fmap denote c)
denote (Union a ) = Union (fmap (fmap denote) a)
denote (UnionLit a b c ) = UnionLit a (denote b) (fmap (fmap denote) c)
denote (Combine a b ) = Combine (denote a) (denote b)
denote (CombineTypes a b ) = CombineTypes (denote a) (denote b)
denote (Prefer a b ) = Prefer (denote a) (denote b)
@ -1856,11 +1865,11 @@ normalizeWithM ctx e0 = loop (denote e0)
kvs' = traverse loop kvs
Union kts -> Union . Dhall.Map.sort <$> kts'
where
kts' = traverse loop kts
kts' = traverse (traverse loop) kts
UnionLit k v kvs -> UnionLit k <$> v' <*> (Dhall.Map.sort <$> kvs')
where
v' = loop v
kvs' = traverse loop kvs
v' = loop v
kvs' = traverse (traverse loop) kvs
Combine x y -> decide <$> loop x <*> loop y
where
decide (RecordLit m) r | Data.Foldable.null m =
@ -1901,6 +1910,22 @@ normalizeWithM ctx e0 = loop (denote e0)
case Dhall.Map.lookup kY kvsX of
Just vX -> loop (App vX vY)
Nothing -> Merge x' y' <$> t'
Field (Union ktsY) kY ->
case Dhall.Map.lookup kY ktsY of
Just Nothing ->
case Dhall.Map.lookup kY kvsX of
Just vX -> return vX
Nothing -> Merge x' y' <$> t'
_ ->
Merge x' y' <$> t'
App (Field (Union ktsY) kY) vY ->
case Dhall.Map.lookup kY ktsY of
Just (Just _) ->
case Dhall.Map.lookup kY kvsX of
Just vX -> loop (App vX vY)
Nothing -> Merge x' y' <$> t'
_ ->
Merge x' y' <$> t'
_ -> Merge x' y' <$> t'
_ -> Merge x' y' <$> t'
where
@ -1912,13 +1937,6 @@ normalizeWithM ctx e0 = loop (denote e0)
case Dhall.Map.lookup x kvs of
Just v -> loop v
Nothing -> Field <$> (RecordLit <$> traverse loop kvs) <*> pure x
Union kvs ->
case Dhall.Map.lookup x kvs of
Just t_ -> Lam x <$> t' <*> pure (UnionLit x (Var (V x 0)) rest)
where
t' = loop t_
rest = Dhall.Map.delete x kvs
Nothing -> Field <$> (Union <$> traverse loop kvs) <*> pure x
_ -> pure (Field r' x)
Project r xs -> do
r' <- loop r
@ -2129,8 +2147,8 @@ isNormalized e0 = loop (denote e0)
OptionalBuild -> True
Record kts -> Dhall.Map.isSorted kts && all loop kts
RecordLit kvs -> Dhall.Map.isSorted kvs && all loop kvs
Union kts -> Dhall.Map.isSorted kts && all loop kts
UnionLit _ v kvs -> loop v && Dhall.Map.isSorted kvs && all loop kvs
Union kts -> Dhall.Map.isSorted kts && all (all loop) kts
UnionLit _ v kvs -> loop v && Dhall.Map.isSorted kvs && all (all loop) kvs
Combine x y -> loop x && loop y && decide x y
where
decide (RecordLit m) _ | Data.Foldable.null m = False
@ -2334,8 +2352,9 @@ subExpressions _ OptionalFold = pure OptionalFold
subExpressions _ OptionalBuild = pure OptionalBuild
subExpressions f (Record a) = Record <$> traverse f a
subExpressions f ( RecordLit a ) = RecordLit <$> traverse f a
subExpressions f (Union a) = Union <$> traverse f a
subExpressions f (UnionLit a b c) = UnionLit a <$> f b <*> traverse f c
subExpressions f (Union a) = Union <$> traverse (traverse f) a
subExpressions f (UnionLit a b c) =
UnionLit a <$> f b <*> traverse (traverse f) c
subExpressions f (Combine a b) = Combine <$> f a <*> f b
subExpressions f (CombineTypes a b) = CombineTypes <$> f a <*> f b
subExpressions f (Prefer a b) = Prefer <$> f a <*> f b

View File

@ -255,7 +255,17 @@ diffKeyVals
-> Map Text (Expr s a)
-> Map Text (Expr s a)
-> [Diff]
diffKeyVals assign kvsL kvsR =
diffKeyVals assign = diffKeysWith assign diffVals
where
diffVals l r = assign <> " " <> diffExpression l r
diffKeysWith
:: Diff
-> (a -> a -> Diff)
-> Map Text a
-> Map Text a
-> [Diff]
diffKeysWith assign diffVals kvsL kvsR =
diffFieldNames <> diffFieldValues <> (if anyEqual then [ ignore ] else [])
where
ksL = Data.Set.fromList (Dhall.Map.keys kvsL)
@ -274,7 +284,7 @@ diffKeyVals assign kvsL kvsR =
<> ignore
]
shared = Dhall.Map.intersectionWith diffExpression kvsL kvsR
shared = Dhall.Map.intersectionWith diffVals kvsL kvsR
diffFieldValues =
filter (not . same) (Dhall.Map.foldMapWithKey adapt shared)
@ -405,8 +415,10 @@ diffRecordLit kvsL kvsR = braced (diffKeyVals equals kvsL kvsR)
diffUnion
:: (Eq a, Pretty a)
=> Map Text (Expr s a) -> Map Text (Expr s a) -> Diff
diffUnion kvsL kvsR = angled (diffKeyVals colon kvsL kvsR)
=> Map Text (Maybe (Expr s a)) -> Map Text (Maybe (Expr s a)) -> Diff
diffUnion kvsL kvsR = angled (diffKeysWith colon diffVals kvsL kvsR)
where
diffVals = diffMaybe (colon <> " ") diffExpression
diffUnionLit
:: (Eq a, Pretty a)
@ -414,8 +426,8 @@ diffUnionLit
-> Text
-> Expr s a
-> Expr s a
-> Map Text (Expr s a)
-> Map Text (Expr s a)
-> Map Text (Maybe (Expr s a))
-> Map Text (Maybe (Expr s a))
-> Diff
diffUnionLit kL kR vL vR kvsL kvsR =
langle
@ -424,8 +436,10 @@ diffUnionLit kL kR vL vR kvsL kvsR =
<> equals
<> " "
<> format " " (diffExpression vL vR)
<> halfAngled (diffKeyVals equals kvsL kvsR)
<> halfAngled (diffKeysWith colon diffVals kvsL kvsR)
where
diffVals = diffMaybe (colon <> " ") diffExpression
halfAngled = enclosed (pipe <> " ") (pipe <> " ") rangle
listSkeleton :: Diff

View File

@ -888,8 +888,8 @@ loadWith expr₀ = case expr₀ of
OptionalBuild -> pure OptionalBuild
Record a -> Record <$> mapM loadWith a
RecordLit a -> RecordLit <$> mapM loadWith a
Union a -> Union <$> mapM loadWith a
UnionLit a b c -> UnionLit <$> pure a <*> loadWith b <*> mapM loadWith c
Union a -> Union <$> mapM (mapM loadWith) a
UnionLit a b c -> UnionLit <$> pure a <*> loadWith b <*> mapM (mapM loadWith) c
Combine a b -> Combine <$> loadWith a <*> loadWith b
CombineTypes a b -> CombineTypes <$> loadWith a <*> loadWith b
Prefer a b -> Prefer <$> loadWith a <*> loadWith b

View File

@ -578,14 +578,12 @@ completeExpression embedded = completeExpression_
kvs <- Text.Megaparsec.many (do
_bar
c <- label
_colon
d <- expression
d <- optional (do _colon; expression)
return (c, d) )
return (UnionLit a b, kvs)
let alternative1 = do
_colon
b <- expression
b <- optional (do _colon; expression)
let alternative2 = do
_bar

View File

@ -849,19 +849,21 @@ prettyCharacterSet characterSet = prettyExpression
| otherwise
= braces (map (prettyKeyValue equals) (Dhall.Map.toList a))
prettyUnion :: Pretty a => Map Text (Expr s a) -> Doc Ann
prettyAlternative (key, Just val) = prettyKeyValue colon (key, val)
prettyAlternative (key, Nothing ) = duplicate (prettyLabel key)
prettyUnion :: Pretty a => Map Text (Maybe (Expr s a)) -> Doc Ann
prettyUnion =
angles . map (prettyKeyValue colon) . Dhall.Map.toList
angles . map prettyAlternative . Dhall.Map.toList
prettyUnionLit
:: Pretty a => Text -> Expr s a -> Map Text (Expr s a) -> Doc Ann
:: Pretty a
=> Text -> Expr s a -> Map Text (Maybe (Expr s a)) -> Doc Ann
prettyUnionLit a b c =
angles (front : map adapt (Dhall.Map.toList c))
angles (front : map prettyAlternative (Dhall.Map.toList c))
where
front = prettyKeyValue equals (a, b)
adapt = prettyKeyValue colon
prettyChunks :: Pretty a => Chunks s a -> Doc Ann
prettyChunks (Chunks a b) =
if any (\(builder, _) -> hasNewLine builder) a || hasNewLine b

View File

@ -480,23 +480,28 @@ completeFunc reversedPrev word
where
listCompletion = map simpleCompletion . filter (word `isPrefixOf`)
algebraicComplete :: [Text.Text] -> Dhall.Expr Dhall.Src Dhall.X -> [Text.Text]
algebraicComplete
:: [Text.Text] -> Dhall.Expr Dhall.Src Dhall.X -> [Text.Text]
algebraicComplete subFields expr =
let keys = fmap ("." <>) . Map.keys
withMap m
| [] <- subFields = keys m
-- Stop on last subField (we care about the keys at this level)
| [_] <- subFields = keys m
| f:fs <- subFields =
maybe
[]
(fmap (("." <> f) <>) . algebraicComplete fs)
(Map.lookup f m)
withMap m =
case subFields of
[] -> keys m
-- Stop on last subField (we care about the keys at this level)
[_] -> keys m
f:fs ->
case Map.lookup f m of
Nothing ->
[]
Just Nothing ->
keys m
Just (Just e) ->
fmap (("." <> f) <>) (algebraicComplete fs e)
in case expr of
Dhall.Core.Record m -> withMap m
Dhall.Core.RecordLit m -> withMap m
Dhall.Core.Record m -> withMap (fmap Just m)
Dhall.Core.RecordLit m -> withMap (fmap Just m)
Dhall.Core.Union m -> withMap m
Dhall.Core.UnionLit _ _ m -> withMap m
_ -> []

View File

@ -1060,18 +1060,36 @@ import Dhall
-- the @Natural@ alternative and the @Right@ tag is used for the @Bool@
-- alternative.
--
-- A union literal specifies the value of one alternative and the types of the
-- remaining alternatives. For example, both of the following union literals
-- have the same type, which is the above union type:
-- You can specify the value of a union constructor like this:
--
-- > < Left = 0 | Right : Bool >
-- > let Union = < Left : Natural | Right : Bool>
-- >
-- > [ Union.Left 0, Union.Right True ] : List Union
--
-- > < Right = True | Left : Natural >
-- In other words, you can access a union constructor as a field of a union
-- type and use that constructor to wrap a value of a type appropriate for
-- that alternative. In the above example, the @Left@ constructor can wrap
-- a @Natural@ value and the @Right@ constructor can wrap a @Bool@ value. We
-- can also confirm that by inspecting their type:
--
-- > $ echo '< Left : Natural | Right : Bool>' > ./Union
--
-- > $ dhall --annotate <<< '(./Union).Left'
-- > < Left : Natural | Right : Bool >.Left
-- > : ∀(Left : Natural) → < Left : Natural | Right : Bool >
--
-- > $ dhall --annotate <<< '(./Union).Right'
-- > < Left : Natural | Right : Bool >.Right
-- > : ∀(Right : Bool) → < Left : Natural | Right : Bool >
--
-- In other words, the @Left@ constructor is a function from a @Natural@ to a
-- value of our @Union@ type and the @Right@ constructor is a separate function
-- from a @Bool@ to that same @Union@ type.
--
-- You can consume a union using the built-in @merge@ function. For example,
-- suppose we want to convert our union to a @Bool@ but we want to behave
-- differently depending on whether or not the union is a @Natural@ wrapped in
-- the @Left@ alternative or a @Bool@ wrapped in the @Right@ alternative. We
-- the @Left@ constructor or a @Bool@ wrapped in the @Right@ constructor . We
-- would write:
--
-- > $ cat > process <<EOF
@ -1085,18 +1103,10 @@ import Dhall
--
-- Now our @./process@ function can handle both alternatives:
--
-- > $ dhall
-- > ./process < Left = 3 | Right : Bool >
-- > <Ctrl-D>
-- > Bool
-- >
-- > $ dhall <<< './process ((./Union).Left 3)'
-- > False
--
-- > $ dhall
-- > ./process < Right = True | Left : Natural >
-- > <Ctrl-D>
-- > Bool
-- >
-- > $ dhall <<< './process ((./Union).Right True)'
-- > True
--
-- Every @merge@ has the following form:
@ -1112,66 +1122,54 @@ import Dhall
-- The @merge@ function selects which function to apply from the record based on
-- which alternative the union selects:
--
-- > merge { Foo = f, ... } < Foo = x | ... > : t = f x : t
-- > merge { Foo = f, ... } (< … >.Foo x) = f x
--
-- So, for example:
--
-- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Left = 3 | Right : Bool > : Bool
-- > = Natural/even 3 : Bool
-- > merge { Left = Natural/even, Right = λ(b : Bool) → b } (< Left : Natural | Right : Bool >.Left 3)
-- > = Natural/even 3
-- > = False
--
-- ... and similarly:
--
-- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural > : Bool
-- > = (λ(b : Bool) → b) True : Bool
-- > merge { Left = Natural/even, Right = λ(b : Bool) → b } (< Left : Natural | Right : Bool >.Right True)
-- > = (λ(b : Bool) → b) True
-- > = True
--
-- Notice that each handler has to return the same type of result (@Bool@ in
-- this case) which must also match the declared result type of the @merge@.
-- this case).
--
-- You can also omit the type annotation when merging a union with one or more
-- alternatives, like this:
--
-- > merge { Left = Natural/even, Right = λ(b : Bool) → b } < Right = True | Left : Natural >
--
-- You can also store more than one value or less than one value within
-- alternatives using Dhall's support for anonymous records. You can nest an
-- anonymous record within a union such as in this type:
-- You can also store more than one value within alternatives using Dhall's
-- support for anonymous records. You can nest an anonymous record within a
-- union such as in this type:
--
-- > < Empty : {} | Person : { name : Text, age : Natural } >
--
-- You can even go a step further and omit the type of an alternative if it
-- stores no data, like this:
--
-- > < Empty | Person : { name : Text, age : Natural } >
--
--
-- This union of records resembles following equivalent Haskell data type:
--
-- > data Example = Empty | Person { name :: Text, age :: Text }
--
-- You could resemble Haskell further by defining convenient constructors for
-- each alternative, like this:
-- Empty alternatives like @Empty@ require no argument:
--
-- > let Empty = < Empty = {=} | Person : { name : Text, age : Natural } >
-- > let Person =
-- > λ(p : { name : Text, age : Natural }) → < Person = p | Empty : {} >
-- > in [ Empty
-- > , Person { name = "John", age = 23 }
-- > , Person { name = "Amy" , age = 25 }
-- > , Empty
-- > ]
--
-- ... but there is no need to do so, since the Dhall language auto-generates
-- constructors for each alternative. You can access each constructor as if it
-- were a field of the union type:
--
-- > let MyType = < Empty : {} | Person : { name : Text, age : Natural } >
-- > in [ MyType.Empty {=}
-- > let MyType = < Empty | Person : { name : Text, age : Natural } >
-- >
-- > in [ MyType.Empty -- Note the absence of any argument to `Empty`
-- > , MyType.Person { name = "John", age = 23 }
-- > , MyType.Person { name = "Amy" , age = 25 }
-- > ]
--
-- You can also extract fields during pattern matching such as in the following
-- function which renders each value to `Text`:
-- ... and when you @merge@ an empty alternative the correspond handler takes no
-- argument:
--
-- > λ(x : < Empty : {} | Person : { name : Text, age : Natural } >)
-- > λ(x : < Empty | Person : { name : Text, age : Natural } >)
-- > → merge
-- > { Empty = λ(_ : {}) → "Unknown"
-- > { Empty = "Unknown" -- Note the absence of a `λ`
-- >
-- > , Person =
-- > λ(person : { name : Text, age : Natural })

View File

@ -25,6 +25,7 @@ import Control.Exception (Exception)
import Data.Data (Data(..))
import Data.Foldable (forM_, toList)
import Data.List.NonEmpty (NonEmpty(..))
import Data.Monoid (First(..))
import Data.Sequence (Seq, ViewL(..))
import Data.Semigroup (Semigroup(..))
import Data.Set (Set)
@ -555,11 +556,13 @@ typeWithA tpa = loop
kts <- Dhall.Map.traverseWithKey process kvs
return (Record kts)
loop ctx e@(Union kts ) = do
case Dhall.Map.uncons kts of
let nonEmpty k mt = First (fmap (\t -> (k, t)) mt)
case getFirst (Dhall.Map.foldMapWithKey nonEmpty kts) of
Nothing -> do
return (Const Type)
Just (k0, t0, rest) -> do
Just (k0, t0) -> do
s0 <- fmap Dhall.Core.normalize (loop ctx t0)
c0 <- case s0 of
@ -569,7 +572,10 @@ typeWithA tpa = loop
_ -> do
Left (TypeError ctx e (InvalidAlternativeType k0 t0))
let process k t = do
let process _ Nothing = do
return ()
process k (Just t) = do
s <- fmap Dhall.Core.normalize (loop ctx t)
c <- case s of
@ -583,7 +589,7 @@ typeWithA tpa = loop
then return ()
else Left (TypeError ctx e (AlternativeAnnotationMismatch k t c k0 t0 c0))
Dhall.Map.unorderedTraverseWithKey_ process rest
Dhall.Map.unorderedTraverseWithKey_ process kts
return (Const c0)
loop ctx e@(UnionLit k v kts) = do
@ -591,7 +597,7 @@ typeWithA tpa = loop
Just _ -> Left (TypeError ctx e (DuplicateAlternative k))
Nothing -> return ()
t <- loop ctx v
let union = Union (Dhall.Map.insert k (Dhall.Core.normalize t) kts)
let union = Union (Dhall.Map.insert k (Just (Dhall.Core.normalize t)) kts)
_ <- loop ctx union
return union
loop ctx e@(Combine kvsX kvsY) = do
@ -711,19 +717,20 @@ typeWithA tpa = loop
else Left (TypeError ctx e (RecordMismatch '⫽' kvsX kvsY constX constY))
return (Record (Dhall.Map.union ktsY ktsX))
loop ctx e@(Merge kvsX kvsY (Just t)) = do
_ <- loop ctx t
loop ctx e@(Merge kvsX kvsY mT) = do
tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)
ktsX <- case tKvsX of
ktsX <- case tKvsX of
Record kts -> return kts
_ -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX))
let ksX = Data.Set.fromList (Dhall.Map.keys ktsX)
tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)
ktsY <- case tKvsY of
ktsY <- case tKvsY of
Union kts -> return kts
_ -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY))
let ksX = Data.Set.fromList (Dhall.Map.keys ktsX)
let ksY = Data.Set.fromList (Dhall.Map.keys ktsY)
let diffX = Data.Set.difference ksX ksY
@ -733,62 +740,69 @@ typeWithA tpa = loop
then return ()
else Left (TypeError ctx e (UnusedHandler diffX))
let process (kY, tY) = do
(mKX, _T) <- do
case mT of
Just _T -> do
return (Nothing, _T)
Nothing -> do
case Dhall.Map.uncons ktsX of
Nothing -> do
Left (TypeError ctx e MissingMergeType)
Just (kX, tX, _) -> do
_T <- do
case Dhall.Map.lookup kX ktsY of
Nothing -> do
Left (TypeError ctx e (UnusedHandler diffX))
Just Nothing -> do
return tX
Just (Just _) ->
case tX of
Pi x _A _T -> do
return (Dhall.Core.shift (-1) (V x 0) _T)
_ -> do
Left (TypeError ctx e (HandlerNotAFunction kX tX))
return (Just kX, _T)
_ <- loop ctx _T
let process kY mTY = do
case Dhall.Map.lookup kY ktsX of
Nothing -> Left (TypeError ctx e (MissingHandler diffY))
Just tX ->
case tX of
Pi y tY' t' -> do
if Dhall.Core.judgmentallyEqual tY tY'
then return ()
else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY'))
let t'' = Dhall.Core.shift (-1) (V y 0) t'
if Dhall.Core.judgmentallyEqual t t''
then return ()
else Left (TypeError ctx e (InvalidHandlerOutputType kY t t''))
_ -> Left (TypeError ctx e (HandlerNotAFunction kY tX))
mapM_ process (Dhall.Map.toList ktsY)
return t
loop ctx e@(Merge kvsX kvsY Nothing) = do
tKvsX <- fmap Dhall.Core.normalize (loop ctx kvsX)
ktsX <- case tKvsX of
Record kts -> return kts
_ -> Left (TypeError ctx e (MustMergeARecord kvsX tKvsX))
let ksX = Data.Set.fromList (Dhall.Map.keys ktsX)
Nothing -> do
Left (TypeError ctx e (MissingHandler diffY))
tKvsY <- fmap Dhall.Core.normalize (loop ctx kvsY)
ktsY <- case tKvsY of
Union kts -> return kts
_ -> Left (TypeError ctx e (MustMergeUnion kvsY tKvsY))
let ksY = Data.Set.fromList (Dhall.Map.keys ktsY)
Just tX -> do
_T <- do
case mTY of
Nothing -> do
return tX
Just _A -> do
case tX of
Pi x _A _T -> do
if Dhall.Core.judgmentallyEqual _A _A
then return ()
else Left (TypeError ctx e (HandlerInputTypeMismatch kY _A _A))
let diffX = Data.Set.difference ksX ksY
let diffY = Data.Set.difference ksY ksX
return (Dhall.Core.shift (-1) (V x 0) _T)
_ -> do
Left (TypeError ctx e (HandlerNotAFunction kY tX))
if Data.Set.null diffX
then return ()
else Left (TypeError ctx e (UnusedHandler diffX))
if Dhall.Core.judgmentallyEqual _T _T
then return ()
else
case mKX of
Nothing -> do
Left (TypeError ctx e (InvalidHandlerOutputType kY _T _T))
Just kX -> do
Left (TypeError ctx e (HandlerOutputTypeMismatch kX _T kY _T))
(kX, t) <- case Dhall.Map.toList ktsX of
[] -> Left (TypeError ctx e MissingMergeType)
(kX, Pi y _ t):_ -> return (kX, Dhall.Core.shift (-1) (V y 0) t)
(kX, tX ):_ -> Left (TypeError ctx e (HandlerNotAFunction kX tX))
let process (kY, tY) = do
case Dhall.Map.lookup kY ktsX of
Nothing -> Left (TypeError ctx e (MissingHandler diffY))
Just tX ->
case tX of
Pi y tY' t' -> do
if Dhall.Core.judgmentallyEqual tY tY'
then return ()
else Left (TypeError ctx e (HandlerInputTypeMismatch kY tY tY'))
let t'' = Dhall.Core.shift (-1) (V y 0) t'
if Dhall.Core.judgmentallyEqual t t''
then return ()
else Left (TypeError ctx e (HandlerOutputTypeMismatch kX t kY t''))
_ -> Left (TypeError ctx e (HandlerNotAFunction kY tX))
mapM_ process (Dhall.Map.toList ktsY)
return t
Dhall.Map.unorderedTraverseWithKey_ process ktsY
return _T
loop ctx e@(Field r x ) = do
t <- fmap Dhall.Core.normalize (loop ctx r)
@ -805,7 +819,8 @@ typeWithA tpa = loop
case Dhall.Core.normalize r of
Union kts ->
case Dhall.Map.lookup x kts of
Just t' -> return (Pi x t' (Union kts))
Just (Just t') -> return (Pi x t' (Union kts))
Just Nothing -> return (Union kts)
Nothing -> Left (TypeError ctx e (MissingField x t))
r' -> Left (TypeError ctx e (CantAccess text r' t))
_ -> do

View File

@ -45,6 +45,9 @@ tests =
, shouldNormalize
"the // operator and sort the fields"
"success/simple/sortOperator"
, shouldNormalize
"enums"
"success/simple/enum"
, multiline
]
@ -194,174 +197,175 @@ preludeExamples =
unitTests :: TestTree
unitTests =
testGroup "Unit tests"
[ shouldOnlyNormalize "ListNormalizeElements"
, shouldOnlyNormalize "TextNormalizeInterpolations"
, shouldOnlyNormalize "RecordTypeEmpty"
, shouldOnlyNormalize "MergeNormalizeArguments"
, shouldOnlyNormalize "OperatorAndNormalizeArguments"
, shouldOnlyNormalize "OperatorEqualEquivalentArguments"
, shouldOnlyNormalize "ListIndexedEmpty"
, shouldOnlyNormalize "OperatorListConcatenateLhsEmpty"
, shouldOnlyNormalize "Variable"
, shouldOnlyNormalize "RecursiveRecordTypeMergeRhsEmpty"
, shouldOnlyNormalize "NaturalToInteger"
, shouldOnlyNormalize "ListReverse"
, shouldOnlyNormalize "MergeWithType"
, shouldOnlyNormalize "OperatorOrLhsFalse"
, shouldOnlyNormalize "IntegerPositive"
, shouldOnlyNormalize "OperatorTimesRhsOne"
, shouldOnlyNormalize "NaturalOdd"
, shouldOnlyNormalize "RecursiveRecordMergeLhsEmpty"
, shouldOnlyNormalize "RightBiasedRecordMergeNormalizeArguments"
, shouldOnlyNormalize "UnionType"
, shouldOnlyNormalize "IntegerNegative"
, shouldOnlyNormalize "NaturalEven"
, shouldOnlyNormalize "OperatorAndRhsTrue"
, shouldOnlyNormalize "NaturalBuildImplementation"
, shouldOnlyNormalize "RecursiveRecordMergeCollision"
, shouldOnlyNormalize "RecursiveRecordMergeNormalizeArguments"
, shouldOnlyNormalize "OperatorAndLhsTrue"
, shouldOnlyNormalize "OperatorPlusOneAndOne"
, shouldOnlyNormalize "IntegerToDouble12"
, shouldOnlyNormalize "IntegerToDouble-12"
, shouldOnlyNormalize "IntegerShow-12"
, shouldOnlyNormalize "ListLengthOne"
, shouldOnlyNormalize "IntegerShow12"
, shouldOnlyNormalize "NaturalFoldZero"
, shouldOnlyNormalize "RecordType"
, shouldOnlyNormalize "IfFalse"
, shouldOnlyNormalize "DoubleShow"
, shouldOnlyNormalize "OptionalBuildFoldFusion"
, shouldOnlyNormalize "NaturalShow"
, shouldOnlyNormalize "ListLength"
, shouldOnlyNormalize "RecursiveRecordTypeMergeCollision"
, shouldOnlyNormalize "RecordEmpty"
, shouldOnlyNormalize "TextLiteral"
, shouldOnlyNormalize "RecordSelectionNormalizeArguments"
, shouldOnlyNormalize "OptionalFold"
, shouldOnlyNormalize "IfTrivial"
, shouldOnlyNormalize "ListBuild"
, shouldOnlyNormalize "OperatorTextConcatenateLhsEmpty"
, shouldOnlyNormalize "LetWithType"
, shouldOnlyNormalize "OptionalFoldSome"
, shouldOnlyNormalize "OptionalBuild"
, shouldOnlyNormalize "ListFoldOne"
, shouldOnlyNormalize "ListLast"
, shouldOnlyNormalize "ListReverseEmpty"
, shouldOnlyNormalize "NaturalEvenZero"
, shouldOnlyNormalize "RecursiveRecordTypeMergeNoCollision"
, shouldOnlyNormalize "NaturalToIntegerOne"
, shouldOnlyNormalize "Natural"
, shouldOnlyNormalize "ListIndexed"
, shouldOnlyNormalize "Integer"
, shouldOnlyNormalize "NaturalIsZero"
, shouldOnlyNormalize "OperatorNotEqualLhsFalse"
, shouldOnlyNormalize "NaturalIsZeroZero"
, shouldOnlyNormalize "OperatorPlusNormalizeArguments"
, shouldOnlyNormalize "RecordSelection"
, shouldOnlyNormalize "OperatorListConcatenateListList"
, shouldOnlyNormalize "OperatorTextConcatenateNormalizeArguments"
, shouldOnlyNormalize "True"
, shouldOnlyNormalize "Bool"
, shouldOnlyNormalize "OperatorNotEqualNormalizeArguments"
, shouldOnlyNormalize "RightBiasedRecordMergeLhsEmpty"
, shouldOnlyNormalize "UnionNormalizeArguments"
, shouldOnlyNormalize "OperatorAndLhsFalse"
, shouldOnlyNormalize "RecordProjection"
, shouldOnlyNormalize "OptionalBuildImplementation"
, shouldOnlyNormalize "OperatorEqualNormalizeArguments"
, shouldOnlyNormalize "Merge"
, shouldOnlyNormalize "Type"
, shouldOnlyNormalize "OperatorListConcatenateRhsEmpty"
, shouldOnlyNormalize "RightBiasedRecordMergeNoCollision"
, shouldOnlyNormalize "RecursiveRecordTypeMergeLhsEmpty"
, shouldOnlyNormalize "IfAlternativesIdentical"
, shouldOnlyNormalize "NoneNatural"
, shouldOnlyNormalize "UnionProjectConstructor"
, shouldOnlyNormalize "ListLastOne"
, shouldOnlyNormalize "IntegerToDouble"
, shouldOnlyNormalize "RightBiasedRecordMergeCollision"
, shouldOnlyNormalize "OperatorOrRhsTrue"
, shouldOnlyNormalize "IfTrue"
, shouldOnlyNormalize "OperatorPlusRhsZero"
, shouldOnlyNormalize "ListHeadOne"
, shouldOnlyNormalize "FunctionApplicationNoSubstitute"
, shouldOnlyNormalize "RecursiveRecordMergeRhsEmpty"
, shouldOnlyNormalize "ListReverseTwo"
, shouldOnlyNormalize "OperatorOrRhsFalse"
, shouldOnlyNormalize "NaturalOddZero"
, shouldOnlyNormalize "UnionTypeNormalizeArguments"
, shouldOnlyNormalize "TextInterpolate"
, shouldOnlyNormalize "Let"
, shouldOnlyNormalize "OperatorTimesLhsOne"
, shouldOnlyNormalize "OperatorOrLhsTrue"
, shouldOnlyNormalize "OperatorPlusLhsZero"
, shouldOnlyNormalize "FunctionNormalizeArguments"
, shouldOnlyNormalize "ListLastEmpty"
, shouldOnlyNormalize "UnionTypeEmpty"
, shouldOnlyNormalize "TextShowAllEscapes"
, shouldOnlyNormalize "RecursiveRecordMergeNoCollision"
, shouldOnlyNormalize "ListNormalizeTypeAnnotation"
, shouldOnlyNormalize "NaturalFoldOne"
, shouldOnlyNormalize "OperatorAndEquivalentArguments"
, shouldOnlyNormalize "SomeNormalizeArguments"
, shouldOnlyNormalize "MergeWithTypeNormalizeArguments"
, shouldOnlyNormalize "OperatorOrNormalizeArguments"
, shouldOnlyNormalize "RecordProjectionNormalizeArguments"
, shouldOnlyNormalize "FunctionApplicationSubstitute"
, shouldOnlyNormalize "OperatorOrEquivalentArguments"
, shouldOnlyNormalize "NaturalFold"
, shouldOnlyNormalize "NaturalEvenOne"
, shouldOnlyNormalize "OperatorTextConcatenateRhsEmpty"
, shouldOnlyNormalize "DoubleLiteral"
, shouldOnlyNormalize "ListHeadEmpty"
, shouldOnlyNormalize "FunctionApplicationCapture"
, shouldOnlyNormalize "RecordProjectionEmpty"
, shouldOnlyNormalize "List"
, shouldOnlyNormalize "NaturalOddOne"
, shouldOnlyNormalize "ListFold"
, shouldOnlyNormalize "OperatorEqualRhsTrue"
, shouldOnlyNormalize "DoubleShowValue"
, shouldOnlyNormalize "OperatorNotEqualEquivalentArguments"
, shouldOnlyNormalize "Text"
, shouldOnlyNormalize "ListIndexedOne"
, shouldOnlyNormalize "IntegerShow"
, shouldOnlyNormalize "Optional"
, shouldOnlyNormalize "OperatorTimesNormalizeArguments"
, shouldOnlyNormalize "NaturalLiteral"
, shouldOnlyNormalize "ListHead"
, shouldOnlyNormalize "ListBuildFoldFusion"
, shouldOnlyNormalize "NaturalIsZeroOne"
, shouldOnlyNormalize "OperatorListConcatenateNormalizeArguments"
, shouldOnlyNormalize "OperatorTimesRhsZero"
[ shouldOnlyNormalize "Bool"
, shouldOnlyNormalize "Double"
, shouldOnlyNormalize "OperatorTimesLhsZero"
, shouldOnlyNormalize "ListFoldEmpty"
, shouldOnlyNormalize "DoubleLiteral"
, shouldOnlyNormalize "DoubleShow"
, shouldOnlyNormalize "DoubleShowValue"
, shouldOnlyNormalize "FunctionApplicationCapture"
, shouldOnlyNormalize "FunctionApplicationNoSubstitute"
, shouldOnlyNormalize "FunctionApplicationNormalizeArguments"
, shouldOnlyNormalize "NaturalShowOne"
, shouldOnlyNormalize "OptionalFoldNone"
, shouldOnlyNormalize "TextShow"
, shouldOnlyNormalize "Kind"
, shouldOnlyNormalize "Sort"
, shouldOnlyNormalize "OperatorTextConcatenateTextText"
, shouldOnlyNormalize "FunctionApplicationSubstitute"
, shouldOnlyNormalize "FunctionNormalizeArguments"
, shouldOnlyNormalize "FunctionTypeNormalizeArguments"
, shouldOnlyNormalize "OperatorNotEqualRhsFalse"
, shouldOnlyNormalize "IfAlternativesIdentical"
, shouldOnlyNormalize "IfFalse"
, shouldOnlyNormalize "IfNormalizePredicateAndBranches"
, shouldOnlyNormalize "IfTrivial"
, shouldOnlyNormalize "IfTrue"
, shouldOnlyNormalize "Integer"
, shouldOnlyNormalize "IntegerNegative"
, shouldOnlyNormalize "IntegerPositive"
, shouldOnlyNormalize "IntegerShow"
, shouldOnlyNormalize "IntegerShow-12"
, shouldOnlyNormalize "IntegerShow12"
, shouldOnlyNormalize "IntegerToDouble"
, shouldOnlyNormalize "IntegerToDouble-12"
, shouldOnlyNormalize "IntegerToDouble12"
, shouldOnlyNormalize "Kind"
, shouldOnlyNormalize "Let"
, shouldOnlyNormalize "LetWithType"
, shouldOnlyNormalize "List"
, shouldOnlyNormalize "ListBuild"
, shouldOnlyNormalize "ListBuildFoldFusion"
, shouldOnlyNormalize "ListBuildImplementation"
, shouldOnlyNormalize "ListFold"
, shouldOnlyNormalize "ListFoldEmpty"
, shouldOnlyNormalize "ListFoldOne"
, shouldOnlyNormalize "ListHead"
, shouldOnlyNormalize "ListHeadEmpty"
, shouldOnlyNormalize "ListHeadOne"
, shouldOnlyNormalize "ListIndexed"
, shouldOnlyNormalize "ListIndexedEmpty"
, shouldOnlyNormalize "ListIndexedOne"
, shouldOnlyNormalize "ListLast"
, shouldOnlyNormalize "ListLastEmpty"
, shouldOnlyNormalize "ListLastOne"
, shouldOnlyNormalize "ListLength"
, shouldOnlyNormalize "ListLengthEmpty"
, shouldOnlyNormalize "ListLengthOne"
, shouldOnlyNormalize "ListNormalizeElements"
, shouldOnlyNormalize "ListNormalizeTypeAnnotation"
, shouldOnlyNormalize "ListReverse"
, shouldOnlyNormalize "ListReverseEmpty"
, shouldOnlyNormalize "ListReverseTwo"
, shouldOnlyNormalize "Merge"
, shouldOnlyNormalize "MergeEmptyAlternative"
, shouldOnlyNormalize "MergeNormalizeArguments"
, shouldOnlyNormalize "MergeWithType"
, shouldOnlyNormalize "MergeWithTypeNormalizeArguments"
, shouldOnlyNormalize "Natural"
, shouldOnlyNormalize "NaturalBuild"
, shouldOnlyNormalize "NaturalBuildFoldFusion"
, shouldOnlyNormalize "TypeAnnotation"
, shouldOnlyNormalize "IfNormalizePredicateAndBranches"
, shouldOnlyNormalize "OperatorEqualLhsTrue"
, shouldOnlyNormalize "Record"
, shouldOnlyNormalize "RecursiveRecordTypeMergeNormalizeArguments"
, shouldOnlyNormalize "UnionNormalizeAlternatives"
, shouldOnlyNormalize "OperatorTimesTwoAndTwo"
, shouldOnlyNormalize "ListBuildImplementation"
, shouldOnlyNormalize "UnionProjectConstructorNormalizeArguments"
, shouldOnlyNormalize "NaturalBuildImplementation"
, shouldOnlyNormalize "NaturalEven"
, shouldOnlyNormalize "NaturalEvenOne"
, shouldOnlyNormalize "NaturalEvenZero"
, shouldOnlyNormalize "NaturalFold"
, shouldOnlyNormalize "NaturalFoldOne"
, shouldOnlyNormalize "NaturalFoldZero"
, shouldOnlyNormalize "NaturalIsZero"
, shouldOnlyNormalize "NaturalIsZeroOne"
, shouldOnlyNormalize "NaturalIsZeroZero"
, shouldOnlyNormalize "NaturalLiteral"
, shouldOnlyNormalize "NaturalOdd"
, shouldOnlyNormalize "NaturalOddOne"
, shouldOnlyNormalize "NaturalOddZero"
, shouldOnlyNormalize "NaturalShow"
, shouldOnlyNormalize "NaturalShowOne"
, shouldOnlyNormalize "NaturalToInteger"
, shouldOnlyNormalize "NaturalToIntegerOne"
, shouldOnlyNormalize "None"
, shouldOnlyNormalize "RightBiasedRecordMergeRhsEmpty"
, shouldOnlyNormalize "UnionSortAlternatives"
, shouldOnlyNormalize "ListLengthEmpty"
, shouldOnlyNormalize "NoneNatural"
, shouldOnlyNormalize "OperatorAndEquivalentArguments"
, shouldOnlyNormalize "OperatorAndLhsFalse"
, shouldOnlyNormalize "OperatorAndLhsTrue"
, shouldOnlyNormalize "OperatorAndNormalizeArguments"
, shouldOnlyNormalize "OperatorAndRhsFalse"
, shouldOnlyNormalize "OperatorAndRhsTrue"
, shouldOnlyNormalize "OperatorEqualEquivalentArguments"
, shouldOnlyNormalize "OperatorEqualLhsTrue"
, shouldOnlyNormalize "OperatorEqualNormalizeArguments"
, shouldOnlyNormalize "OperatorEqualRhsTrue"
, shouldOnlyNormalize "OperatorListConcatenateLhsEmpty"
, shouldOnlyNormalize "OperatorListConcatenateListList"
, shouldOnlyNormalize "OperatorListConcatenateNormalizeArguments"
, shouldOnlyNormalize "OperatorListConcatenateRhsEmpty"
, shouldOnlyNormalize "OperatorNotEqualEquivalentArguments"
, shouldOnlyNormalize "OperatorNotEqualLhsFalse"
, shouldOnlyNormalize "OperatorNotEqualNormalizeArguments"
, shouldOnlyNormalize "OperatorNotEqualRhsFalse"
, shouldOnlyNormalize "OperatorOrEquivalentArguments"
, shouldOnlyNormalize "OperatorOrLhsFalse"
, shouldOnlyNormalize "OperatorOrLhsTrue"
, shouldOnlyNormalize "OperatorOrNormalizeArguments"
, shouldOnlyNormalize "OperatorOrRhsFalse"
, shouldOnlyNormalize "OperatorOrRhsTrue"
, shouldOnlyNormalize "OperatorPlusLhsZero"
, shouldOnlyNormalize "OperatorPlusNormalizeArguments"
, shouldOnlyNormalize "OperatorPlusOneAndOne"
, shouldOnlyNormalize "OperatorPlusRhsZero"
, shouldOnlyNormalize "OperatorTextConcatenateLhsEmpty"
, shouldOnlyNormalize "OperatorTextConcatenateNormalizeArguments"
, shouldOnlyNormalize "OperatorTextConcatenateRhsEmpty"
, shouldOnlyNormalize "OperatorTextConcatenateTextText"
, shouldOnlyNormalize "OperatorTimesLhsOne"
, shouldOnlyNormalize "OperatorTimesLhsZero"
, shouldOnlyNormalize "OperatorTimesNormalizeArguments"
, shouldOnlyNormalize "OperatorTimesRhsOne"
, shouldOnlyNormalize "OperatorTimesRhsZero"
, shouldOnlyNormalize "OperatorTimesTwoAndTwo"
, shouldOnlyNormalize "Optional"
, shouldOnlyNormalize "OptionalBuild"
, shouldOnlyNormalize "OptionalBuildFoldFusion"
, shouldOnlyNormalize "OptionalBuildImplementation"
, shouldOnlyNormalize "OptionalFold"
, shouldOnlyNormalize "OptionalFoldNone"
, shouldOnlyNormalize "OptionalFoldSome"
, shouldOnlyNormalize "Record"
, shouldOnlyNormalize "RecordEmpty"
, shouldOnlyNormalize "RecordProjection"
, shouldOnlyNormalize "RecordProjectionEmpty"
, shouldOnlyNormalize "RecordProjectionNormalizeArguments"
, shouldOnlyNormalize "RecordSelection"
, shouldOnlyNormalize "RecordSelectionNormalizeArguments"
, shouldOnlyNormalize "RecordType"
, shouldOnlyNormalize "RecordTypeEmpty"
, shouldOnlyNormalize "RecursiveRecordMergeCollision"
, shouldOnlyNormalize "RecursiveRecordMergeLhsEmpty"
, shouldOnlyNormalize "RecursiveRecordMergeNoCollision"
, shouldOnlyNormalize "RecursiveRecordMergeNormalizeArguments"
, shouldOnlyNormalize "RecursiveRecordMergeRhsEmpty"
, shouldOnlyNormalize "RecursiveRecordTypeMergeCollision"
, shouldOnlyNormalize "RecursiveRecordTypeMergeLhsEmpty"
, shouldOnlyNormalize "RecursiveRecordTypeMergeNoCollision"
, shouldOnlyNormalize "RecursiveRecordTypeMergeNormalizeArguments"
, shouldOnlyNormalize "RecursiveRecordTypeMergeRhsEmpty"
, shouldOnlyNormalize "RightBiasedRecordMergeCollision"
, shouldOnlyNormalize "RightBiasedRecordMergeLhsEmpty"
, shouldOnlyNormalize "RightBiasedRecordMergeNoCollision"
, shouldOnlyNormalize "RightBiasedRecordMergeNormalizeArguments"
, shouldOnlyNormalize "RightBiasedRecordMergeRhsEmpty"
, shouldOnlyNormalize "SomeNormalizeArguments"
, shouldOnlyNormalize "Sort"
, shouldOnlyNormalize "Text"
, shouldOnlyNormalize "TextInterpolate"
, shouldOnlyNormalize "TextLiteral"
, shouldOnlyNormalize "TextNormalizeInterpolations"
, shouldOnlyNormalize "TextShow"
, shouldOnlyNormalize "TextShowAllEscapes"
, shouldOnlyNormalize "True"
, shouldOnlyNormalize "Type"
, shouldOnlyNormalize "TypeAnnotation"
, shouldOnlyNormalize "UnionNormalizeAlternatives"
, shouldOnlyNormalize "UnionNormalizeArguments"
, shouldOnlyNormalize "UnionProjectConstructor"
, shouldOnlyNormalize "UnionProjectConstructorNormalizeArguments"
, shouldOnlyNormalize "UnionSortAlternatives"
, shouldOnlyNormalize "UnionType"
, shouldOnlyNormalize "UnionTypeEmpty"
, shouldOnlyNormalize "UnionTypeNormalizeArguments"
, shouldOnlyNormalize "Variable"
]
alphaNormalizationTests :: TestTree

View File

@ -53,12 +53,12 @@ unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do
Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty)
(Dhall.Core.Union
(Dhall.Map.fromList
[ ("Foo",Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)]))
, ("Bar",Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Bool),("_2",Dhall.Core.Bool),("_3",Dhall.Core.Bool)]))
, ("Baz",Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Integer),("_2",Dhall.Core.Integer)]))
[ ("Foo",Just (Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)])))
, ("Bar",Just (Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Bool),("_2",Dhall.Core.Bool),("_3",Dhall.Core.Bool)])))
, ("Baz",Just (Dhall.Core.Record (Dhall.Map.fromList [
("_1",Dhall.Core.Integer),("_2",Dhall.Core.Integer)])))
]
)
)

View File

@ -1,5 +1,6 @@
let MyType = < Empty : {} | Person : { name : Text, age : Natural } >
in [ MyType.Empty {=}
let MyType = < Empty | Person : { name : Text, age : Natural } >
in [ MyType.Empty -- Note the absence of any argument to `Empty`
, MyType.Person { name = "John", age = 23 }
, MyType.Person { name = "Amy" , age = 25 }
]

View File

@ -1,4 +1,6 @@
[ < Empty = {=} | Person : { age : Natural, name : Text } >
, < Person = { age = 23, name = "John" } | Empty : {} >
, < Person = { age = 25, name = "Amy" } | Empty : {} >
[ < Empty | Person : { age : Natural, name : Text } >.Empty
, < Empty | Person : { age : Natural, name : Text } >.Person
{ age = 23, name = "John" }
, < Empty | Person : { age : Natural, name : Text } >.Person
{ age = 25, name = "Amy" }
]