Releases: dhall-lang/dhall-lang
v23.0.0
Breaking changes:
-
New support for
Bytes
literalsYou can now store
Bytes
within Dhall, which comprises two changes to the
language:-
A new
Bytes
type -
Support for
Bytes
literals 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
Bytes
is now a reserved
identifier. -
-
New
{Date,Time,TimeZone}/show
builtinsYou can now render temporal literals as
Text
representing 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/show
are now reserved identifiers.
New features:
-
Add
dhall to-directory-tree
related definitionsThis adds several utilities underneath a new
Prelude.DirectoryTree
hierarchy for working with thedhall to-directory-tree
subcommand.
Specifically, the sucommand now supports setting metadata on generated paths
and the utilities support working with this new metadata-related
functionality. -
Add
Prelude.List.mapMaybe
andPrelude.Map.mapMaybe
These come in handy when transforming
List
s inMap
s 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
showConstructor
keyword for converting union alternative toText
You can now render the constructor name for a union alternative using the
showConstructor
keyword, like this:let Example = < A : Bool | B > in [ showConstructor (Example.A True), showConstructor Example.B ]
… which evaluates to:
[ "A", "B" ]
showConstructor
also works onOptional
andBool
values, too:>>> showConstructor (None Bool) "None" >>> showConstructor (Some True) "Some" >>> showConstructor True "True" >>> showConstructor False "False"
-
Require non-empty whitespace after
let
bindingBefore 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
with
support for modifyingOptional
valuesYou can now use a path component named
?
to modify values nested inside of
Optional
types, like this:>>> { x = Some { y = 2 } } with x.?.y = 3 { x = Some { y = 3 } }
You can even use this to update an
Optional
value 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
merge
andtoMap
annotations 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) → a
is 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
merge
andtoMap
expressions 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
/TimeZone
are 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.dhall
file
in one of the following locations:~/.config/dhall/headers.dhall
${XDG_CONFIG_HOME}/dhall/headers.dhall
env: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
Map
key is of the formhost:port
and 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 theusing
keyword, 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-Agent
header would now also be set to"dhall"
, but the
Authorization
would 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}ASCII
utilitiesYou can now uppercase and lowercase ASCII characters in
Text
using 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.render
outputPrelude.JSON.render
now renders$
as itself instead of\u0024
Other changes:
v20.0.0
Breaking changes:
-
Text/replace
waits to replace interpolatedText
Text/replace
will now not reduce if theText
literal 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
x
was substituted into the interpolated
Text
literal before or afterText/replace
performed the replacement.This is a technically breaking change because it would change the integrity
check for any expression replacing aText
literal with abstract
interpolated subexpressions. In practice, you are unlikely to be affected by
this change. -
Normalize
Text/replace
when "needle" is empty and other arguments are abstractText/replace
will 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.render
now correctly escapes unsanitized inputThe new version of the utility uses
Text/replace
to 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:
-
if
expressions 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
if
expressions consistent with the behavior of
the equivalentmerge
expression 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
with
directly rather than via desugaringThe standard now defines
with
directly, rather than via a
desugaring step. This changes the normalization behaviour ofwith
expressions in three ways: first,with
expressions 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: certainwith
expressions 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 = 3
This 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
containwith
expressions may change.
New features:
-
This change adds a builtin
Text/replace
which 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 ofwith
expressions, mainly in order to avoid pathological
time and space complexity when interpreting chainedwith
expressions, like:r with x.y = a with z = b
Along the way, this changes how
with
expressions 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 awith
expression where the
left-hand side of thewith
expression 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 thewith
expression, which will then
not affect the final hash.
New features:
Other changes:
-
Fixes and improvements to the Prelude:
v17.1.0
New features:
-
The language now permits trailing delimiters, including:
-
Trailing commas for record literals:
{ x = 1, y = 2, }
-
Trailing commas for record types:
{ x : Natural, y : Natural, }
-
Trailing commas for list literals:
[ 1, 2, ]
-
Trailing bars for union types:
< Left : Natural | Right : Bool | >
These trailing delimiters will allow you to format your code in a style
more familiar to JavaScript / Python / Go / Rust programmers. -
-
Add
.dhall
extensions on Prelude filesAll Prelude files now include a version with a
.dhall
extension, both for
consistency with the rest of the ecosystem and to automatically trigger
correct syntax highlighting and editor support based on the.dhall
extension.The old files without the extension are still present (so this change is
backwards-compatible), but now all they do is re-export the file with the
.dhall
extension.New additions to the Prelude will require the
.dhall
extension and won't
include the extension-free counterpart.
Other changes:
-
Fixes and improvements to the standard: