Releases: dhall-lang/dhall-lang
v23.1.0
New features:
-
Support binary literals for
NaturalandIntegerliteralsYou can now use
0b…notation forNaturalliterals and±0b…notation for
Integerliterals to write them out in binary.For example:
0b101010 -- Same as: 42 +0b1011 -- Same as: +11 -0b111 -- Same as: -7
Other changes:
- Fixes and improvements to the standard:
- Fixes and improvements to the standard test suite:
v23.0.0
Breaking changes:
-
New support for
BytesliteralsYou can now store
Byteswithin Dhall, which comprises two changes to the
language:-
A new
Bytestype -
Support for
Bytesliterals of the form0x"…"
For example, the following Dhall literal represents a valid sequence of four
bytes:0x"00FF12DE"
This is a technically breaking change because
Bytesis now a reserved
identifier. -
-
New
{Date,Time,TimeZone}/showbuiltinsYou can now render temporal literals as
Textrepresenting valid Dhall
source code:Date/show : Date → Text Time/show : Time → Text TimeZone/show : TimeZone → Text
For example:
⊢ Date/show 2000-01-01 "2000-01-01" ⊢ Time/show 11:59:59 "11:59:59" ⊢ TimeZone/show -08:00 "-08:00"
This is a technically breaking change because
Date/show,Time/show, and
TimeZone/showare now reserved identifiers.
New features:
-
Add
dhall to-directory-treerelated definitionsThis adds several utilities underneath a new
Prelude.DirectoryTree
hierarchy for working with thedhall to-directory-treesubcommand.
Specifically, the sucommand now supports setting metadata on generated paths
and the utilities support working with this new metadata-related
functionality. -
Add
Prelude.List.mapMaybeandPrelude.Map.mapMaybeThese come in handy when transforming
Lists inMaps when you also want to
filter out keys.
Other changes:
- Fixes and improvements to the standard:
- Fixes and improvements to the standard test suite:
v22.0.0
Breaking changes:
-
New
showConstructorkeyword for converting union alternative toTextYou can now render the constructor name for a union alternative using the
showConstructorkeyword, like this:let Example = < A : Bool | B > in [ showConstructor (Example.A True), showConstructor Example.B ]
… which evaluates to:
[ "A", "B" ]
showConstructoralso works onOptionalandBoolvalues, too:>>> showConstructor (None Bool) "None" >>> showConstructor (Some True) "Some" >>> showConstructor True "True" >>> showConstructor False "False"
-
Require non-empty whitespace after
letbindingBefore this change an expression like this was permitted:
let x = 3let y = x in y
… because the grammar did not require non-empty whitespace in between
let
bindings. Now the grammar requires non-empty whitespace in between bindings
so the above expression is no longer permitted.
New features:
-
Add
withsupport for modifyingOptionalvaluesYou can now use a path component named
?to modify values nested inside of
Optionaltypes, like this:>>> { x = Some { y = 2 } } with x.?.y = 3 { x = Some { y = 3 } }
You can even use this to update an
Optionalvalue without any record fields:>>> Some 0 with ? = 1 Some 1
Other changes:
- Fixes and improvements to the standard:
- Fixes and improvements to the standard test suite:
v21.1.0
New features:
-
Fix
mergeandtoMapannotations to behave the same as ordinary type annotationsBefore this change an expression like this:
λ(x : <>) → merge {=} x : ∀(a : Type) → a
… would not have type-checked as it would have been parsed as:
λ(x : <>) → (merge {=} x) : ∀(a : Type) → a
… where the
∀(a : Type) → ais treated as an ordinary type annotation and
not amerge-specific annotation used to handle the special case of an empty
merge.After this change, the type annotations that are specially-associated with
mergeandtoMapexpressions to handle their empty cases behave the same as
ordinary type annotations.
Other changes:
v21.0.0
Breaking changes:
-
Standardize support for dates / times / time zones
Dhall now provides language support for time types and literals, including
almost all combinations of dates, time, and time zones.For example, these are all valid temporal literals and their corresponding
types:2020-01-01 : Date 00:00:00 : Time +00:00 : TimeZone 2020-01-01T00:00:00 : { date : Date, time : Time } 00:00:00+00:00 : { time : Time, timeZone : TimeZone } 2020-01-01T00:00:00+00:00 : { date : Date, time : Time, timeZone : TimeZone }
Currently there are not yet built-in functions associated with temporal
values. This change only adds the new types and support for projecting out
components of complex literals as record fields.This is a breaking change because
Date/Time/TimeZoneare now
reserved identifier names. -
Change
?to only fall back on absent importsThe
?operator will no longer recover from type errors, parse errors,
hash mismatches, or cyclic imports found within the first import. The second
import will only be tried if the first import cannot be retrieved at all
(either from cache or the specified location).This is a breaking change because some Dhall programs which used to succeed
will now fail. Specifically, a program which relied on the?operator to
recover from non-import-related errors will now begin to fail.
Other changes:
- Fixes and improvements to the standard test suite:
New features:
-
Add support for origin-based header configuration
You can now customize headers out-of-band by creating a
headers.dhallfile
in one of the following locations:~/.config/dhall/headers.dhall${XDG_CONFIG_HOME}/dhall/headers.dhallenv:DHALL_HEADERS
This headers file has type
Map Text (Map Text Text)and might look something
like this:toMap { `raw.githubusercontent.com:443` = toMap { Authorization = "TOKEN" } }Where each outer
Mapkey is of the formhost:portand the nnerMap
contains custom header-value pairs. These custom headers are supplied
to any imports destined for tht origin.These out-of-band custom headers work in conjunction with the in-band custom
headers supplied by theusingkeyword, but the out-of-band custome headers
take precedence. For example, if one were to import:https://raw.githubusercontent.com/example.dhall using ( toMap { Authorization = "ANOTHER TOKEN" , User-Agent = "dhall" } )
… then the
User-Agentheader would now also be set to"dhall", but the
Authorizationwould still be"TOKEN".
v20.2.0
New features:
-
Dhall files can now begin with any number of lines starting with
#!.This comes in handy if you want to specify how to interpret the file using the
Unix shebang convention, like this:#!/usr/bin/env -S dhall text --file "Hello, world!"
See also: Add support for extra Unix shebangs
-
Add
Prelude.Text.{lower,upper}ASCIIutilitiesYou can now uppercase and lowercase ASCII characters in
Textusing these
two new Prelude utilities -
This lets you fold a list in the opposite direction of
Prelude.List.fold
Other changes:
-
Fixes and improvements to the standard:
-
Fixes and improvements to the Prelude:
v20.1.0
New features:
-
Improve
Prelude.JSON.renderoutputPrelude.JSON.rendernow renders$as itself instead of\u0024
Other changes:
v20.0.0
Breaking changes:
-
Text/replacewaits to replace interpolatedTextText/replacewill now not reduce if theTextliteral to replace has any
interpolated subexpressions.For example, before this change, the following expression:
λ(x : Text) → Text/replace "a" "b" "a${x}"
… would normalize to:
λ(x : Text) → "b${x}"
After this change, the former expression is in normal form and won't reduce
further so long as the interpolated expression remains abstract.This change was made to fix the fact that the old behavior for
Text/replace
was not confluent, meaning that the behavior would change depending on which
order normalization rules were applied. For example, the following
expression would give different results:let x = "a" in Text/replace "a" "b" "b${x}"
… depending on whether or not
xwas substituted into the interpolated
Textliteral before or afterText/replaceperformed the replacement.This is a technically breaking change because it would change the integrity
check for any expression replacing aTextliteral with abstract
interpolated subexpressions. In practice, you are unlikely to be affected by
this change. -
Normalize
Text/replacewhen "needle" is empty and other arguments are abstractText/replacewill now always normalize if the first argument is the empty
string, regardless of whether or not the other two arguments are abstract.Or in other words:
Text/replace "" replacement haystack
… will always reduce to:
haystack
This is a technically breaking change along the same lines as the previous
change and is also unlikely to affect you in practice. -
Prelude.XML.rendernow correctly escapes unsanitized inputThe new version of the utility uses
Text/replaceto escape unsanitized
input, in order to guarantee that the rendered XML is always well-formed.This is a breaking change because the rendered output will be different if the
input contained special characters (like<). However, it's more likely that
this change will fix your code rather than break it (unless you were depending
on the old behavior as an escape hatch for XML injection).
New features:
-
ifexpressions can now return types and kindsFor example, the following expressions are now valid:
if b then Natural else Integer
if b then Type → Type else Type
This makes the behavior of
ifexpressions consistent with the behavior of
the equivalentmergeexpression for a union of type< True | False >.
Other changes:
-
Fixes and improvements to the standard:
-
Fixes and improvements to the standard test suite:
v19.0.0
Breaking changes:
-
Implement
withdirectly rather than via desugaringThe standard now defines
withdirectly, rather than via a
desugaring step. This changes the normalization behaviour ofwith
expressions in three ways: first,withexpressions on abstract
variables such asλ(r : { foo : Text }) → r with bar = "baz"
will now remain unchanged after normalization, whereas previously
this expression would have normalised to:λ(r : { foo : Text }) → r ⫽ { bar = "baz" }
The second way normalization has changed is a consequence of the
above: certainwithexpressions used to take advantage of
simplification of⫽expressions. For example:(e with k = v).k
used to normalize to
v, but now normalizes to itself.The third change to normalization is that it is no longer a type
error to add multiple layers of nesting into a record at once:{} with x.y.z = 3This expression normalizes to:
{ x = { y = { z = 3 }}}which can also be written:
{ x.y.z = 3 }This is technically a breaking change due to the changes to
normalization; this also means that the semantic hash of files which
containwithexpressions may change.
New features:
-
This change adds a builtin
Text/replacewhich makes it possible to
replace substrings inside a Text literal. It has typeText → Text → Text. For example, the following expression normalizes to
"Hello, world!":Text/replace "Hey" "Hello" "Hey, world!"
For more information, see the Text/replace documentation.
v18.0.0
Breaking changes:
-
The standard now gives implementations more freedom to optimize the
β-reduction ofwithexpressions, mainly in order to avoid pathological
time and space complexity when interpreting chainedwithexpressions, like:r with x.y = a with z = b
Along the way, this changes how
withexpressions are encoded in the
binary representation, which means that this is a technically breaking
change.In practice, you are unlikely to to be affected by this change, except for the
rare case where you protect an import with a semantic integrity check and the
contents of the protected import contain awithexpression where the
left-hand side of thewithexpression is abstract, such as this one:λ(x: { a : Natural}) → x with a = 42
Other than that, semantic integrity checks are not affected because the
interpreter will β-normalize away thewithexpression, which will then
not affect the final hash.
New features:
Other changes:
-
Fixes and improvements to the Prelude: