Merge pull request #886 from dhall-lang/gabriel/dhall_nix

Merge `dhall-nix` into `dhall-haskell`
This commit is contained in:
Gabriel Gonzalez 2019-04-10 06:42:07 -07:00 committed by GitHub
commit 505bd9240d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 1689 additions and 0 deletions

76
dhall-nix/.travis.yml Normal file
View File

@ -0,0 +1,76 @@
# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
language: c
sudo: false
cache:
directories:
- $HOME/.cabsnap
- $HOME/.cabal/packages
before_cache:
- rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
- rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
matrix:
include:
- env: CABALVER=1.24 GHCVER=8.0.1
compiler: ": #GHC 8.0.1"
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
before_install:
- unset CC
- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
install:
- cabal --version
- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
then
zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
$HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
fi
- travis_retry cabal update -v
- sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
- cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
- sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
# check whether current requested install-plan matches cached package-db snapshot
- if diff -u $HOME/.cabsnap/installplan.txt installplan.txt;
then
echo "cabal build-cache HIT";
rm -rfv .ghc;
cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
else
echo "cabal build-cache MISS";
rm -rf $HOME/.cabsnap;
mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
cabal install --only-dependencies --enable-tests --enable-benchmarks;
fi
# snapshot package-db on cache miss
- if [ ! -d $HOME/.cabsnap ];
then
echo "snapshotting package-db to build-cache";
mkdir $HOME/.cabsnap;
cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
fi
# Here starts the actual work to be performed for the package under test;
# any command which exits with a non-zero exit code causes the build to fail.
script:
- if [ -f configure.ac ]; then autoreconf -i; fi
- cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
- cabal build # this builds all libraries and executables (including tests/benchmarks)
- cabal test
- cabal check
- cabal sdist # tests that a source-distribution can be generated
# Check that the resulting source distribution can be built & installed.
# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
# `cabal install --force-reinstalls dist/*-*.tar.gz`
- SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
(cd dist && cabal install --force-reinstalls "$SRC_TGZ")
# EOF

24
dhall-nix/LICENSE Normal file
View File

@ -0,0 +1,24 @@
Copyright (c) 2017 Gabriel Gonzalez
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Gabriel Gonzalez nor the names of other contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

81
dhall-nix/README.md Normal file
View File

@ -0,0 +1,81 @@
# `dhall-nix 1.1.6`
This `dhall-nix` package provides a Dhall to Nix compiler. You can use this
compiler to program Nix using the Dhall language. This package targets people
who wish Nix had a type system.
## Quick start
If you have Nix installed then you can build and run this package using:
```bash
$ nix-build -A dhall-nix release.nix
$ result/bin/dhall-to-nix <<< "λ(x : Bool) → x == False"
x: x == false
$ result/bin/dhall-to-nix <<< "{ foo = 1, bar = True }"
{ bar = true; foo = 1; }
$ result/bin/dhall-to-nix <<< "< Left = 2 | Right : Natural >"
{ Left, Right }: Left 2
```
However, this package is also designed to be used directly from Nix. You can
use the following `dhallToNix` utility to translate Dhall source code to the
corresponding Nix expression directly within Nix:
```nix
dhallToNix = code :
let
file = builtins.toFile "dhall-expr" code;
drv = pkgs.stdenv.mkDerivation {
name = "dhall-expr-as-nix";
buildCommand = ''
dhall-to-nix <<< "${file}" > $out
'';
buildInputs = [ pkgs.haskellPackages.dhall-nix ];
};
in
import "${drv}";
```
The above `dhallToNix` utility is now in `nixpkgs` so you can use `pkgs.dhallToNix`
to transform Dhall expressions to Nix expressions
## Development status
[![Build Status](https://travis-ci.org/Gabriel439/Haskell-Dhall-Nix-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Dhall-Nix-Library)
I don't expect this library to change unless:
* ... the Dhall language changes, which is possible but not very likely
* ... there are bugs, but the test suite in [release.nix](./release.nix) should
protect against this
## License (BSD 3-clause)
Copyright (c) 2017 Gabriel Gonzalez
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Gabriel Gonzalez nor the names of other contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2
dhall-nix/Setup.hs Normal file
View File

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

51
dhall-nix/dhall-nix.cabal Normal file
View File

@ -0,0 +1,51 @@
Name: dhall-nix
Version: 1.1.6
Cabal-Version: >=1.8.0.2
Build-Type: Simple
Tested-With: GHC == 8.0.1
License: BSD3
License-File: LICENSE
Copyright: 2017 Gabriel Gonzalez
Author: Gabriel Gonzalez
Maintainer: Gabriel439@gmail.com
Bug-Reports: https://github.com/Gabriel439/Haskell-Dhall-Nix-Library/issues
Synopsis: Dhall to Nix compiler
Description:
Use this package if you want to compile Dhall expressions to the Nix language.
You can use this package as a library or an executable:
.
* See the "Dhall.Nix" module if you want to use this package as a library
.
* Use the @dhall-to-nix@ program from this package if you want an executable
.
The "Dhall.Nix" module also contains instructions for how to use this package
Category: Compiler
Source-Repository head
Type: git
Location: https://github.com/Gabriel439/Haskell-Dhall-Nix-Library
Library
Hs-Source-Dirs: src
Build-Depends:
base >= 4.8.0.0 && < 5 ,
containers < 0.7 ,
data-fix < 0.3 ,
dhall >= 1.19 && < 1.22,
hnix >= 0.5 && < 0.7 ,
neat-interpolation < 0.4 ,
text >= 0.8.0.0 && < 1.3
Exposed-Modules:
Dhall.Nix
GHC-Options: -Wall
Executable dhall-to-nix
Hs-Source-Dirs: exec
Main-Is: Main.hs
Build-Depends:
base ,
dhall ,
dhall-nix ,
hnix ,
optparse-generic >= 1.1.1 && < 1.4,
text
GHC-Options: -Wall

52
dhall-nix/exec/Main.hs Normal file
View File

@ -0,0 +1,52 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Exception (SomeException)
import System.Exit (ExitCode(..))
import qualified Control.Exception
import qualified Data.Text.IO
import qualified Dhall
import qualified Dhall.Import
import qualified Dhall.Nix
import qualified Dhall.Parser
import qualified Dhall.TypeCheck
import qualified GHC.IO.Encoding
import qualified Nix.Pretty
import qualified Options.Generic
import qualified System.Exit
import qualified System.IO
main :: IO ()
main = handle (Dhall.detailed (do
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
() <- Options.Generic.getRecord "Compile Dhall to Nix"
inText <- Data.Text.IO.getContents
expr <- case Dhall.Parser.exprFromText "(stdin)" inText of
Left err -> Control.Exception.throwIO err
Right expr -> return expr
expr' <- Dhall.Import.load expr
case Dhall.TypeCheck.typeOf expr' of
Left err -> Control.Exception.throwIO err
Right _ -> return ()
nix <- case Dhall.Nix.dhallToNix expr' of
Left err -> Control.Exception.throwIO err
Right nix -> return nix
print (Nix.Pretty.prettyNix nix) ))
handle :: IO a -> IO a
handle = Control.Exception.handle handler
where
handler :: SomeException -> IO a
handler e = case Control.Exception.fromException e of
Just ExitSuccess -> do
Control.Exception.throwIO e
_ -> do
System.IO.hPutStrLn System.IO.stderr ""
System.IO.hPrint System.IO.stderr e
System.Exit.exitFailure

View File

@ -0,0 +1,18 @@
{ mkDerivation, base, containers, deepseq, erf, process, random
, stdenv, template-haskell, tf-random, transformers
}:
mkDerivation {
pname = "QuickCheck";
version = "2.12.6.1";
sha256 = "0b2aa7f5c625b5875c36f5f548926fcdaedf4311bd3a4c291fcf10b8d7faa170";
revision = "1";
editedCabalFile = "0w5gygp6pmyjzjjx5irfflcbx586zfnqidq669ssqqfsadf944xv";
libraryHaskellDepends = [
base containers deepseq erf random template-haskell tf-random
transformers
];
testHaskellDepends = [ base deepseq process ];
homepage = "https://github.com/nick8325/quickcheck";
description = "Automatic testing of Haskell programs";
license = stdenv.lib.licenses.bsd3;
}

33
dhall-nix/nix/aeson.nix Normal file
View File

@ -0,0 +1,33 @@
{ mkDerivation, attoparsec, base, base-compat, base-orphans
, base16-bytestring, bytestring, containers, contravariant, deepseq
, directory, dlist, filepath, generic-deriving, ghc-prim, hashable
, hashable-time, integer-logarithms, primitive, QuickCheck
, quickcheck-instances, scientific, stdenv, tagged, tasty
, tasty-hunit, tasty-quickcheck, template-haskell, text
, th-abstraction, time, time-locale-compat, unordered-containers
, uuid-types, vector
}:
mkDerivation {
pname = "aeson";
version = "1.4.2.0";
sha256 = "75ce71814a33d5e5568208e6806a8847e7ba47fea74d30f6a8b1b56ecb318bd0";
revision = "1";
editedCabalFile = "067y82gq86740j2zj4y6v7z9b5860ncg2g9lfnrpsnb9jqm7arl1";
libraryHaskellDepends = [
attoparsec base base-compat bytestring containers contravariant
deepseq dlist ghc-prim hashable primitive scientific tagged
template-haskell text th-abstraction time time-locale-compat
unordered-containers uuid-types vector
];
testHaskellDepends = [
attoparsec base base-compat base-orphans base16-bytestring
bytestring containers directory dlist filepath generic-deriving
ghc-prim hashable hashable-time integer-logarithms QuickCheck
quickcheck-instances scientific tagged tasty tasty-hunit
tasty-quickcheck template-haskell text time time-locale-compat
unordered-containers uuid-types vector
];
homepage = "https://github.com/bos/aeson";
description = "Fast JSON parsing and encoding";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,9 @@
{ mkDerivation, base, stdenv, unix }:
mkDerivation {
pname = "base-compat";
version = "0.10.5";
sha256 = "990aea21568956d44ab018c5dbfbaea014b9a0d5295d29ca7550149419a6fb41";
libraryHaskellDepends = [ base unix ];
description = "A compatibility layer for base";
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,14 @@
{ mkDerivation, base, ghc-prim, hspec, hspec-discover, QuickCheck
, stdenv
}:
mkDerivation {
pname = "base-orphans";
version = "0.8.1";
sha256 = "442bd63aed102e753b2fed15df8ae19f35ee07af26590da63837c523b64a99db";
libraryHaskellDepends = [ base ghc-prim ];
testHaskellDepends = [ base hspec QuickCheck ];
testToolDepends = [ hspec-discover ];
homepage = "https://github.com/haskell-compat/base-orphans#readme";
description = "Backwards-compatible orphan instances for base";
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,15 @@
{ mkDerivation, aeson, aeson-pretty, base, cborg, scientific
, stdenv, text, unordered-containers, vector
}:
mkDerivation {
pname = "cborg-json";
version = "0.2.1.0";
sha256 = "3fb6b54e6ddd322880689fb461f7911aca45b9758482c9f9949619c7d7b52006";
libraryHaskellDepends = [
aeson aeson-pretty base cborg scientific text unordered-containers
vector
];
homepage = "https://github.com/well-typed/cborg";
description = "A library for encoding JSON as CBOR";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,10 @@
{ mkDerivation, base, StateVar, stdenv, transformers }:
mkDerivation {
pname = "contravariant";
version = "1.5";
sha256 = "6ef067b692ad69ffff294b953aa85f3ded459d4ae133c37896222a09280fc3c2";
libraryHaskellDepends = [ base StateVar transformers ];
homepage = "http://github.com/ekmett/contravariant/";
description = "Contravariant functors";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,18 @@
{ mkDerivation, base, containers, data-fix, dhall, hnix
, neat-interpolation, optparse-generic, stdenv, text
}:
mkDerivation {
pname = "dhall-nix";
version = "1.1.6";
src = ./..;
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
base containers data-fix dhall hnix neat-interpolation text
];
executableHaskellDepends = [
base dhall hnix optparse-generic text
];
description = "Dhall to Nix compiler";
license = stdenv.lib.licenses.bsd3;
}

41
dhall-nix/nix/dhall.nix Normal file
View File

@ -0,0 +1,41 @@
{ mkDerivation, aeson, aeson-pretty, ansi-terminal, base
, bytestring, case-insensitive, cborg, cborg-json, containers
, contravariant, criterion, cryptonite, deepseq, Diff, directory
, doctest, dotgen, exceptions, filepath, haskeline, http-client
, http-client-tls, http-types, lens-family-core, megaparsec, memory
, mockery, mtl, optparse-applicative, parsers, prettyprinter
, prettyprinter-ansi-terminal, QuickCheck, quickcheck-instances
, repline, scientific, serialise, stdenv, tasty, tasty-hunit
, tasty-quickcheck, template-haskell, text, transformers
, unordered-containers, uri-encode, vector
}:
mkDerivation {
pname = "dhall";
version = "1.21.0";
sha256 = "9b22cc6f7694ef2f5d5d6fa66727044622b9905b2a9da0cdf376c75ad3b9df0e";
revision = "1";
editedCabalFile = "0ap1490jks9hmwf73vlrj7bsfrf4m5yvgqxx3ix57w23ia5gy662";
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
aeson aeson-pretty ansi-terminal base bytestring case-insensitive
cborg cborg-json containers contravariant cryptonite Diff directory
dotgen exceptions filepath haskeline http-client http-client-tls
http-types lens-family-core megaparsec memory mtl
optparse-applicative parsers prettyprinter
prettyprinter-ansi-terminal repline scientific serialise
template-haskell text transformers unordered-containers uri-encode
vector
];
executableHaskellDepends = [ base ];
testHaskellDepends = [
base bytestring cborg containers deepseq directory doctest filepath
mockery prettyprinter QuickCheck quickcheck-instances serialise
tasty tasty-hunit tasty-quickcheck text transformers vector
];
benchmarkHaskellDepends = [
base bytestring containers criterion directory serialise text
];
description = "A configuration language guaranteed to terminate";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,49 @@
{ rev # The Git revision of nixpkgs to fetch
, sha256 # The SHA256 of the downloaded data
, outputSha256 ? null # The SHA256 fixed-output hash
, system ? builtins.currentSystem # This is overridable if necessary
}:
if (0 <= builtins.compareVersions builtins.nixVersion "1.12")
# In Nix 1.12, we can just give a `sha256` to `builtins.fetchTarball`.
then (
builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
sha256 = outputSha256;
})
# This hack should at least work for Nix 1.11
else (
(rec {
tarball = import <nix/fetchurl.nix> {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
inherit sha256;
};
builtin-paths = import <nix/config.nix>;
script = builtins.toFile "nixpkgs-unpacker" ''
"$coreutils/mkdir" "$out"
cd "$out"
"$gzip" --decompress < "$tarball" | "$tar" -x --strip-components=1
'';
nixpkgs = builtins.derivation ({
name = "nixpkgs-${builtins.substring 0 6 rev}";
builder = builtins.storePath builtin-paths.shell;
args = [ script ];
inherit tarball system;
tar = builtins.storePath builtin-paths.tar;
gzip = builtins.storePath builtin-paths.gzip;
coreutils = builtins.storePath builtin-paths.coreutils;
} // (if null == outputSha256 then { } else {
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = outputSha256;
}));
}).nixpkgs)

16
dhall-nix/nix/free.nix Normal file
View File

@ -0,0 +1,16 @@
{ mkDerivation, base, comonad, containers, distributive, exceptions
, mtl, profunctors, semigroupoids, stdenv, template-haskell
, transformers, transformers-base
}:
mkDerivation {
pname = "free";
version = "5.1";
sha256 = "70424d5c82dea36a0a29c4f5f6bc047597a947ad46f3d66312e47bbee2eeea84";
libraryHaskellDepends = [
base comonad containers distributive exceptions mtl profunctors
semigroupoids template-haskell transformers transformers-base
];
homepage = "http://github.com/ekmett/free/";
description = "Monads for free";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,26 @@
{ mkDerivation, base, base16-bytestring, base64-bytestring, binary
, bytestring, containers, cryptohash-md5, cryptohash-sha1
, cryptohash-sha256, directory, filepath, hashable, mtl, process
, regex-base, regex-tdfa-text, stdenv, tasty, tasty-discover
, tasty-hspec, tasty-hunit, tasty-quickcheck, temporary, text, unix
, unordered-containers, vector
}:
mkDerivation {
pname = "hnix-store-core";
version = "0.1.0.0";
sha256 = "878c9a1dcb535b76efb7af392f9a9e75b954ce4ebb75acac91036a6c3c1d3df7";
libraryHaskellDepends = [
base base16-bytestring binary bytestring containers cryptohash-md5
cryptohash-sha1 cryptohash-sha256 directory filepath hashable mtl
regex-base regex-tdfa-text text unix unordered-containers vector
];
testHaskellDepends = [
base base64-bytestring binary bytestring containers directory
process tasty tasty-discover tasty-hspec tasty-hunit
tasty-quickcheck temporary text
];
testToolDepends = [ tasty-discover ];
homepage = "https://github.com/haskell-nix/hnix-store";
description = "Core effects for interacting with the Nix store";
license = stdenv.lib.licenses.asl20;
}

67
dhall-nix/nix/hnix.nix Normal file
View File

@ -0,0 +1,67 @@
{ mkDerivation, aeson, array, base, base16-bytestring, binary
, bytestring, comonad, containers, contravariant, criterion
, cryptohash-md5, cryptohash-sha1, cryptohash-sha256
, cryptohash-sha512, data-fix, deepseq, dependent-sum
, deriving-compat, Diff, directory, exceptions, fetchgit, filepath
, free, generic-random, Glob, hashable, hashing, haskeline
, hedgehog, hnix-store-core, http-client, http-client-tls
, http-types, interpolate, lens-family, lens-family-core
, lens-family-th, logict, megaparsec, monad-control, monadlist, mtl
, optparse-applicative, parser-combinators, pretty-show
, prettyprinter, process, ref-tf, regex-tdfa, regex-tdfa-text
, repline, scientific, semigroups, serialise, split, stdenv, syb
, tasty, tasty-hedgehog, tasty-hunit, tasty-quickcheck, tasty-th
, template-haskell, text, these, time, transformers
, transformers-base, unix, unordered-containers, vector, xml
}:
mkDerivation {
pname = "hnix";
version = "0.6.0";
src = fetchgit {
url = "https://github.com/haskell-nix/hnix.git";
sha256 = "15g4brrl8qj5dhx54x0rc4212q11bljvv4wh5qz199p2pk7gbqwk";
rev = "3d89159ee425bf4671a6e4a610c1527d7ce251a9";
};
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
aeson array base base16-bytestring binary bytestring comonad
containers contravariant cryptohash-md5 cryptohash-sha1
cryptohash-sha256 cryptohash-sha512 data-fix deepseq dependent-sum
deriving-compat directory exceptions filepath free hashable hashing
haskeline hnix-store-core http-client http-client-tls http-types
interpolate lens-family lens-family-core lens-family-th logict
megaparsec monad-control monadlist mtl optparse-applicative
parser-combinators pretty-show prettyprinter process ref-tf
regex-tdfa regex-tdfa-text scientific semigroups serialise split
syb template-haskell text these time transformers transformers-base
unix unordered-containers vector xml
];
executableHaskellDepends = [
aeson base base16-bytestring bytestring comonad containers
cryptohash-md5 cryptohash-sha1 cryptohash-sha256 cryptohash-sha512
data-fix deepseq exceptions filepath free hashing haskeline mtl
optparse-applicative pretty-show prettyprinter ref-tf repline
serialise template-haskell text time transformers
unordered-containers
];
testHaskellDepends = [
base base16-bytestring bytestring containers cryptohash-md5
cryptohash-sha1 cryptohash-sha256 cryptohash-sha512 data-fix
deepseq dependent-sum Diff directory exceptions filepath
generic-random Glob hashing hedgehog interpolate megaparsec mtl
optparse-applicative pretty-show prettyprinter process serialise
split tasty tasty-hedgehog tasty-hunit tasty-quickcheck tasty-th
template-haskell text time transformers unix unordered-containers
];
benchmarkHaskellDepends = [
base base16-bytestring bytestring containers criterion
cryptohash-md5 cryptohash-sha1 cryptohash-sha256 cryptohash-sha512
data-fix deepseq exceptions filepath hashing mtl
optparse-applicative serialise template-haskell text time
transformers unordered-containers
];
homepage = "https://github.com/haskell-nix/hnix#readme";
description = "Haskell implementation of the Nix language";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,28 @@
{ mkDerivation, array, async, base, blaze-builder, bytestring
, case-insensitive, containers, cookie, deepseq, directory
, exceptions, filepath, ghc-prim, hspec, http-types, memory
, mime-types, monad-control, network, network-uri, random, stdenv
, stm, streaming-commons, text, time, transformers, zlib
}:
mkDerivation {
pname = "http-client";
version = "0.5.14";
sha256 = "8e50409704021c51a8955b2d03bfec900ebc3e11fbaebf973f2e654d7bde3647";
revision = "1";
editedCabalFile = "0xw5ac4cvcd4hcwl7j12adi7sgffjryqhk0x992k3qs1cxyv5028";
libraryHaskellDepends = [
array base blaze-builder bytestring case-insensitive containers
cookie deepseq exceptions filepath ghc-prim http-types memory
mime-types network network-uri random stm streaming-commons text
time transformers
];
testHaskellDepends = [
async base blaze-builder bytestring case-insensitive containers
deepseq directory hspec http-types monad-control network
network-uri streaming-commons text time transformers zlib
];
doCheck = false;
homepage = "https://github.com/snoyberg/http-client";
description = "An HTTP client engine";
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,17 @@
{ mkDerivation, array, base, bytestring, case-insensitive, doctest
, hspec, QuickCheck, quickcheck-instances, stdenv, text
}:
mkDerivation {
pname = "http-types";
version = "0.12.3";
sha256 = "4e8a4a66477459fa436a331c75e46857ec8026283df984d54f90576cd3024016";
libraryHaskellDepends = [
array base bytestring case-insensitive text
];
testHaskellDepends = [
base bytestring doctest hspec QuickCheck quickcheck-instances text
];
homepage = "https://github.com/aristidb/http-types";
description = "Generic HTTP types for Haskell (for both client and server code)";
license = stdenv.lib.licenses.bsd3;
}

39
dhall-nix/nix/lens.nix Normal file
View File

@ -0,0 +1,39 @@
{ mkDerivation, array, base, base-orphans, bifunctors, bytestring
, Cabal, cabal-doctest, call-stack, comonad, containers
, contravariant, criterion, deepseq, directory, distributive
, doctest, exceptions, filepath, free, generic-deriving, ghc-prim
, hashable, HUnit, kan-extensions, mtl, nats, parallel, profunctors
, QuickCheck, reflection, semigroupoids, semigroups, simple-reflect
, stdenv, tagged, template-haskell, test-framework
, test-framework-hunit, test-framework-quickcheck2
, test-framework-th, text, th-abstraction, transformers
, transformers-compat, unordered-containers, vector, void
}:
mkDerivation {
pname = "lens";
version = "4.17";
sha256 = "473664de541023bef44aa29105abbb1e35542e9254cdc846963183e0dd3f08cc";
setupHaskellDepends = [ base Cabal cabal-doctest filepath ];
libraryHaskellDepends = [
array base base-orphans bifunctors bytestring call-stack comonad
containers contravariant distributive exceptions filepath free
ghc-prim hashable kan-extensions mtl parallel profunctors
reflection semigroupoids semigroups tagged template-haskell text
th-abstraction transformers transformers-compat
unordered-containers vector void
];
testHaskellDepends = [
base bytestring containers deepseq directory doctest filepath
generic-deriving HUnit mtl nats parallel QuickCheck semigroups
simple-reflect test-framework test-framework-hunit
test-framework-quickcheck2 test-framework-th text transformers
unordered-containers vector
];
benchmarkHaskellDepends = [
base bytestring comonad containers criterion deepseq
generic-deriving transformers unordered-containers vector
];
homepage = "http://github.com/ekmett/lens/";
description = "Lenses, Folds and Traversals";
license = stdenv.lib.licenses.bsd2;
}

View File

@ -0,0 +1,25 @@
{ mkDerivation, base, bytestring, case-insensitive, containers
, criterion, deepseq, hspec, hspec-expectations, mtl
, parser-combinators, QuickCheck, scientific, stdenv, text
, transformers, weigh
}:
mkDerivation {
pname = "megaparsec";
version = "7.0.4";
sha256 = "325ba5cee8cdef91e351fb2db0b38562f8345b0bcdfed97045671357501de8c1";
libraryHaskellDepends = [
base bytestring case-insensitive containers deepseq mtl
parser-combinators scientific text transformers
];
testHaskellDepends = [
base bytestring case-insensitive containers hspec
hspec-expectations mtl parser-combinators QuickCheck scientific
text transformers
];
benchmarkHaskellDepends = [
base containers criterion deepseq text weigh
];
homepage = "https://github.com/mrkkrp/megaparsec";
description = "Monadic parser combinators";
license = stdenv.lib.licenses.bsd2;
}

View File

@ -0,0 +1,15 @@
{ mkDerivation, base, base-prelude, HTF, megaparsec, stdenv
, template-haskell, text
}:
mkDerivation {
pname = "neat-interpolation";
version = "0.3.2.4";
sha256 = "de7370d938ffd8c7b52d732f4f088387ed8216cf9767d818e99b7ec827931752";
libraryHaskellDepends = [
base base-prelude megaparsec template-haskell text
];
testHaskellDepends = [ base-prelude HTF ];
homepage = "https://github.com/nikita-volkov/neat-interpolation";
description = "A quasiquoter for neat and simple multiline text interpolation";
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,15 @@
{ mkDerivation, ansi-wl-pprint, base, bytestring, process
, QuickCheck, stdenv, transformers, transformers-compat
}:
mkDerivation {
pname = "optparse-applicative";
version = "0.14.3.0";
sha256 = "72476302fe555a508917b2d7d6121c7b58ea5434cdc08aeb5d4b652e8f0e7663";
libraryHaskellDepends = [
ansi-wl-pprint base process transformers transformers-compat
];
testHaskellDepends = [ base bytestring QuickCheck ];
homepage = "https://github.com/pcapriotti/optparse-applicative";
description = "Utilities and combinators for parsing command line options";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,10 @@
{ mkDerivation, base, stdenv }:
mkDerivation {
pname = "parser-combinators";
version = "1.0.1";
sha256 = "edf5ab8fa69a04334baa8707252036563a8339a96a86956c90febe93830cea32";
libraryHaskellDepends = [ base ];
homepage = "https://github.com/mrkkrp/parser-combinators";
description = "Lightweight package providing commonly useful parser combinators";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,19 @@
{ mkDerivation, array, base, filepath, ghc-prim, happy
, haskell-lexer, pretty, stdenv, text
}:
mkDerivation {
pname = "pretty-show";
version = "1.9.5";
sha256 = "b095bebb79951d2e25a543a591844fb638165672d7b95d325844611297ba423f";
isLibrary = true;
isExecutable = true;
enableSeparateDataOutput = true;
libraryHaskellDepends = [
array base filepath ghc-prim haskell-lexer pretty text
];
libraryToolDepends = [ happy ];
executableHaskellDepends = [ base ];
homepage = "http://wiki.github.com/yav/pretty-show";
description = "Tools for working with derived `Show` instances and generic inspection of values";
license = stdenv.lib.licenses.mit;
}

11
dhall-nix/nix/repline.nix Normal file
View File

@ -0,0 +1,11 @@
{ mkDerivation, base, containers, haskeline, mtl, process, stdenv
}:
mkDerivation {
pname = "repline";
version = "0.2.0.0";
sha256 = "ecc72092d0340b896ee6bf96bf6645694dbcd33361725a2cd28c5ab5d60c02de";
libraryHaskellDepends = [ base containers haskeline mtl process ];
homepage = "https://github.com/sdiehl/repline";
description = "Haskeline wrapper for GHCi-like REPL interfaces";
license = stdenv.lib.licenses.mit;
}

View File

@ -0,0 +1,20 @@
{ mkDerivation, base, base-orphans, bifunctors, Cabal
, cabal-doctest, comonad, containers, contravariant, distributive
, doctest, hashable, stdenv, tagged, template-haskell, transformers
, transformers-compat, unordered-containers
}:
mkDerivation {
pname = "semigroupoids";
version = "5.3.2";
sha256 = "61a8213df437ee96a20b1c6dec8b5c573e4e0f338eb2061739a67f471d6b9d05";
setupHaskellDepends = [ base Cabal cabal-doctest ];
libraryHaskellDepends = [
base base-orphans bifunctors comonad containers contravariant
distributive hashable tagged template-haskell transformers
transformers-compat unordered-containers
];
testHaskellDepends = [ base doctest ];
homepage = "http://github.com/ekmett/semigroupoids";
description = "Semigroupoids: Category sans id";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,29 @@
{ mkDerivation, aeson, array, base, binary, bytestring, cborg
, cereal, cereal-vector, containers, criterion, deepseq, directory
, filepath, ghc-prim, half, hashable, pretty, primitive, QuickCheck
, quickcheck-instances, semigroups, stdenv, store, tar, tasty
, tasty-hunit, tasty-quickcheck, text, time, unordered-containers
, vector, zlib
}:
mkDerivation {
pname = "serialise";
version = "0.2.1.0";
sha256 = "043efc1130b4202f080c5b7d2c319098df032b060655d8193f1fcdbfa3f159a5";
libraryHaskellDepends = [
array base bytestring cborg containers ghc-prim half hashable
primitive text time unordered-containers vector
];
testHaskellDepends = [
base bytestring cborg containers directory filepath primitive
QuickCheck quickcheck-instances tasty tasty-hunit tasty-quickcheck
text time unordered-containers vector
];
benchmarkHaskellDepends = [
aeson array base binary bytestring cborg cereal cereal-vector
containers criterion deepseq directory filepath ghc-prim half
pretty semigroups store tar text time vector zlib
];
homepage = "https://github.com/well-typed/cborg";
description = "A binary serialisation library for Haskell values";
license = stdenv.lib.licenses.bsd3;
}

25
dhall-nix/nix/these.nix Normal file
View File

@ -0,0 +1,25 @@
{ mkDerivation, aeson, base, base-compat, bifunctors, binary
, containers, data-default-class, deepseq, hashable, keys, lens
, mtl, QuickCheck, quickcheck-instances, semigroupoids, stdenv
, tasty, tasty-quickcheck, transformers, transformers-compat
, unordered-containers, vector, vector-instances
}:
mkDerivation {
pname = "these";
version = "0.7.6";
sha256 = "9464b83d98e626360a8ad9836ba77e5201cd1e9c89b95b1b11a28ef3c23ac746";
libraryHaskellDepends = [
aeson base base-compat bifunctors binary containers
data-default-class deepseq hashable keys lens mtl QuickCheck
semigroupoids transformers transformers-compat unordered-containers
vector vector-instances
];
testHaskellDepends = [
aeson base base-compat bifunctors binary containers hashable lens
QuickCheck quickcheck-instances tasty tasty-quickcheck transformers
unordered-containers vector
];
homepage = "https://github.com/isomorphism/these";
description = "An either-or-both data type & a generalized 'zip with padding' typeclass";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -0,0 +1,10 @@
{ mkDerivation, base, old-locale, stdenv, time }:
mkDerivation {
pname = "time-locale-compat";
version = "0.1.1.5";
sha256 = "07ff1566de7d851423a843b2de385442319348c621d4f779b3d365ce91ac502c";
libraryHaskellDepends = [ base old-locale time ];
homepage = "https://github.com/khibino/haskell-time-locale-compat";
description = "Compatibile module for time-format locale";
license = stdenv.lib.licenses.bsd3;
}

19
dhall-nix/nix/vector.nix Normal file
View File

@ -0,0 +1,19 @@
{ mkDerivation, base, base-orphans, deepseq, ghc-prim, HUnit
, primitive, QuickCheck, random, stdenv, template-haskell
, test-framework, test-framework-hunit, test-framework-quickcheck2
, transformers
}:
mkDerivation {
pname = "vector";
version = "0.12.0.2";
sha256 = "52e89dacaff10bedb8653181963cae928f9674a099bb706713dae83994bbc0f3";
libraryHaskellDepends = [ base deepseq ghc-prim primitive ];
testHaskellDepends = [
base base-orphans HUnit primitive QuickCheck random
template-haskell test-framework test-framework-hunit
test-framework-quickcheck2 transformers
];
homepage = "https://github.com/haskell/vector";
description = "Efficient Arrays";
license = stdenv.lib.licenses.bsd3;
}

304
dhall-nix/release.nix Normal file
View File

@ -0,0 +1,304 @@
let
fetchNixpkgs = import ./nix/fetchNixpkgs.nix;
nixpkgs = fetchNixpkgs {
rev = "1d4de0d552ae9aa66a5b8dee5fb0650a4372d148";
sha256 = "09qx58dp1kbj7cpzp8ahbqfbbab1frb12sh1qng87rybcaz0dz01";
outputSha256 = "0xpqc1fhkvvv5dv1zmas2j1q27mi7j7dgyjcdh82mlgl1q63i660";
};
mass = function: names: haskellPackagesNew: haskellPackagesOld:
let
toNameValue = name: {
inherit name;
value = function haskellPackagesOld."${name}";
};
in
builtins.listToAttrs (map toNameValue names);
config = {
packageOverrides = pkgs: {
haskellPackages = pkgs.haskellPackages.override (old: {
overrides =
let
dontCheck =
mass pkgs.haskell.lib.dontCheck [
"adjunctions"
"base-orphans"
"base64-bytestring"
"cereal"
"blaze-builder"
"neat-interpolation"
"pureMD5"
"pem"
"lens"
"th-orphans"
"mockery"
"megaparsec"
"lens-family-th"
"network-uri"
"invariant"
"interpolate"
"http-types"
"parsers"
"dhall"
"aeson"
"half"
"generic-deriving"
"distributive"
"deriving-compat"
"monad-control"
"logging-facade"
"bifunctors"
"exceptions"
"cborg-json"
"cryptohash-sha512"
"Diff"
"hashable"
"hnix"
"hnix-store-core"
"optparse-generic"
"serialise"
"SHA"
"these"
"unordered-containers"
"vector"
];
extension = haskellPackagesNew: haskellPackagesOld: {
dhall-nix =
pkgs.haskell.lib.failOnAllWarnings
(pkgs.haskell.lib.justStaticExecutables
haskellPackagesOld.dhall-nix
);
};
in
pkgs.lib.fold
pkgs.lib.composeExtensions
(old.overrides or (_: _: {}))
[ (pkgs.haskell.lib.packagesFromDirectory { directory = ./nix; })
dontCheck
extension
];
}
);
};
};
pkgs =
import nixpkgs { inherit config; };
inherit (pkgs) dhallToNix;
in
{ dhall-nix = pkgs.haskellPackages.dhall-nix;
shell = pkgs.haskellPackages.dhall-nix.env;
# Test that various Dhall to Nix conversions work
tests =
let
testConst = dhallToNix "Type";
testLam = dhallToNix "λ(x : Bool) x";
testPi = dhallToNix "Bool Bool";
testApp = dhallToNix "λ(f : Bool Bool) λ(x : Bool) f x";
testLet = dhallToNix "λ(b : Bool) let x = b in x";
testAnnot = dhallToNix "True : Bool";
testBool = dhallToNix "Bool";
testBoolLit = dhallToNix "True";
testBoolAnd = dhallToNix "λ(l : Bool) λ(r : Bool) l && r";
testBoolOr = dhallToNix "λ(l : Bool) λ(r : Bool) l || r";
testBoolEQ = dhallToNix "λ(l : Bool) λ(r : Bool) l == r";
testBoolNE = dhallToNix "λ(l : Bool) λ(r : Bool) l != r";
testBoolIf = dhallToNix "λ(x : Bool) if x then True else False";
testNatural = dhallToNix "Natural";
testNaturalLit = dhallToNix "123";
testNaturalFold = dhallToNix ''
λ(x : Natural)
Natural/fold x Natural (λ(n : Natural) 2 + n) 0
'';
testNaturalBuild = dhallToNix ''
λ(b : Bool)
Natural/build
( λ(natural : Type)
λ(succ : natural natural)
λ(zero : natural)
if b then succ zero else zero
)
'';
testNaturalIsZero = dhallToNix "Natural/isZero";
testNaturalEven = dhallToNix "Natural/even";
testNaturalOdd = dhallToNix "Natural/odd";
testNaturalToInteger = dhallToNix "Natural/toInteger";
testNaturalShow = dhallToNix "Natural/show";
testNaturalPlus = dhallToNix "λ(x : Natural) λ(y : Natural) x + y";
testNaturalTimes = dhallToNix "λ(x : Natural) λ(y : Natural) x * y";
testInteger = dhallToNix "Integer";
testIntegerLit = dhallToNix "+123";
testIntegerShow = dhallToNix "Integer/show";
testDouble = dhallToNix "Double";
testTextLit = dhallToNix ''"ABC"'';
testInterpolation = dhallToNix ''λ(x : Text) "ABC''${x}GHI"'' "DEF";
testTextAppend = dhallToNix "λ(x : Text) λ(y : Text) x ++ y";
testList = dhallToNix "List Natural";
testListLit = dhallToNix "[1, 2, 3] : List Natural";
testListAppend = dhallToNix ''
λ(xs : List Natural) λ(ys : List Natural) xs # ys
'';
testListBuild = dhallToNix ''
λ(b : Bool)
List/build
Natural
( λ(list : Type)
λ(cons : Natural list list)
λ(nil : list)
if b then cons 1 (cons 2 (cons 3 nil)) else nil
)
'';
testListFold = dhallToNix ''
List/fold
Natural
([1, 2, 3] : List Natural)
Natural
'';
testListLength = dhallToNix "List/length Natural";
testListHead = dhallToNix "List/head Natural";
testListLast = dhallToNix "List/last Natural";
testListIndexed = dhallToNix "List/indexed Natural";
testListReverse = dhallToNix "List/reverse Natural";
testOptional = dhallToNix "Optional";
testOptionalLit = dhallToNix ''
λ(b : Bool)
if b
then ([0] : Optional Natural)
else ([] : Optional Natural)
'';
testOptionalFold = dhallToNix ''
Optional/fold
Natural
([1] : Optional Natural)
Natural
'';
testOptionalBuild = dhallToNix ''
λ(b : Bool)
Optional/build
Natural
( λ(optional : Type)
λ(just : Natural optional)
λ(nothing : optional)
if b then just 1 else nothing
)
'';
testNone = dhallToNix "None Natural";
testSome = dhallToNix "Some 4";
testRecord = dhallToNix "{}";
testRecordLit = dhallToNix "{ foo = 1, bar = True}";
testUnion = dhallToNix "< Left : Natural | Right : Bool >";
testUnionLit = dhallToNix "< Left = 2 | Right : Bool >";
testCombine = dhallToNix ''
λ(x : { foo : { bar : Text } })
λ(y : { foo : { baz : Bool } })
x y
'';
testCombineTypes = dhallToNix ''
{ foo : Text } { bar : Bool, baz : Natural }
'';
testMerge = dhallToNix ''
λ(r : < Left : Natural | Right : Bool >)
merge
{ Left = Natural/isZero, Right = λ(b : Bool) b }
r : Bool
'';
testField = dhallToNix "λ(r : { foo : Bool, bar : Text }) r.foo";
testProject = dhallToNix ''
λ(r : { foo : Bool, bar : Text, baz : Natural }) r.{ foo, bar }
'';
in
assert (testConst == {});
assert (testLam true == true);
assert (testPi == {});
assert (testApp (b : b) true == true);
assert (testLet true == true);
assert (testAnnot == true);
assert (testBool == {});
assert (testBoolLit == true);
assert (testBoolAnd true false == false);
assert (testBoolOr true false == true);
assert (testBoolEQ true false == false);
assert (testBoolNE true false == true);
assert (testBoolIf true == true);
assert (testNatural == {});
assert (testNaturalLit == 123);
assert (testNaturalFold 123 == 246);
assert (testNaturalBuild true == 1);
assert (testNaturalBuild false == 0);
assert (testNaturalIsZero 0 == true);
assert (testNaturalIsZero 3 == false);
assert (testNaturalEven 2 == true);
assert (testNaturalEven 3 == false);
assert (testNaturalOdd 2 == false);
assert (testNaturalToInteger 2 == 2);
assert (testNaturalShow 2 == "2");
assert (testNaturalOdd 3 == true);
assert (testNaturalPlus 2 3 == 5);
assert (testNaturalTimes 2 3 == 6);
assert (testInteger == {});
assert (testIntegerLit == 123);
assert (testIntegerShow 2 == "+2");
assert (testIntegerShow (-3) == "-3");
assert (testDouble == {});
assert (testTextLit == "ABC");
assert (testInterpolation == "ABCDEFGHI");
assert (testTextAppend "ABC" "DEF" == "ABCDEF");
assert (testList == {});
assert (testListLit == [1 2 3]);
assert (testListAppend [1 2 3] [4 5 6] == [1 2 3 4 5 6]);
assert (testListBuild false == []);
assert (testListBuild true == [1 2 3]);
assert (testListFold (x : y: x + y) 0 == 6);
assert (testListLength [1 2 3] == 3);
assert (testListLength [] == 0);
assert (testListHead [1 2 3] == 1);
assert (testListHead [] == null);
assert (testListLast [1 2 3] == 3);
assert (testListLast [] == null);
assert (testListIndexed [2 3 5] == [
{ index = 0; value = 2; }
{ index = 1; value = 3; }
{ index = 2; value = 5; }
]);
assert (testListReverse [1 2 3] == [3 2 1]);
assert (testOptional {} == {});
assert (testOptionalLit true == 0);
assert (testOptionalLit false == null);
assert (testOptionalFold (n : n) 0 == 1);
assert (testOptionalBuild true == 1);
assert (testOptionalBuild false == null);
assert (testRecord == {});
assert (testRecordLit == { foo = 1; bar = true; });
assert (testUnion == {});
assert (testUnionLit { Left = n : n == 0; Right = b : b; } == false);
assert ((testCombine { foo.baz = true; } { foo.bar = "ABC"; }) == {
foo = {
baz = true;
bar = "ABC";
};
});
assert (testCombineTypes == {});
assert (testMerge ({ Left, Right }: Left 2) == false);
assert (testField { foo = true; bar = "ABC"; } == true);
assert (testProject { foo = true; bar = "ABC"; baz = 1; } == {
foo = true;
bar = "ABC";
});
pkgs.stdenv.mkDerivation {
name = "tests-pass";
buildCommand = "touch $out";
};
}

1
dhall-nix/shell.nix Normal file
View File

@ -0,0 +1 @@
(import ./release.nix).shell

500
dhall-nix/src/Dhall/Nix.hs Normal file
View File

@ -0,0 +1,500 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeFamilies #-}
{-| This library only exports a single `dhallToNix` function for translating a
Dhall syntax tree to a Nix syntax tree for the @hnix@ library
See the @dhall@ package if you would like to transform Dhall source code
into a Dhall syntax tree. Similarly, see the @hnix@ package if you would
like to translate a Nix syntax tree into Nix source code.
This package also provides a @dhall-to-nix@ executable which you can use to
compile Dhall source code directly to Nix source code for your convenience.
Any Dhall expression can be converted into an equivalent Nix expression.
For example, Dhall records can be converted into Nix records:
> $ dhall-to-nix <<< "{ foo = 1, bar = True }"
> { bar = true; foo = 1; }
... and you can also convert Dhall functions to Nix functions, too:
> $ dhall-to-nix <<< "λ(x : Bool) → x == False"
> x: x == false
Many Dhall expressions have a straightforward translation to Nix expressions
but there are some translations that are not as obvious. The following
section documents these trickier conversions:
First, all Dhall types translate to an empty record:
> $ dhall-to-nix <<< "Integer"
> {}
Polymorphic Dhall functions translate to Nix functions that ignore their
type argument:
> $ dhall-to-nix <<< "List/head"
> t: xs: if xs == []
> then null
> else builtins.head xs
`Optional` values translate to @null@ if missing or the unwrapped value if
present:
> $ dhall-to-nix <<< "[] : Optional Integer"
> null
> $ dhall-to-nix <<< "[1] : Optional Integer"
> 1
Unions are Church-encoded:
> $ dhall-to-nix <<< "< Left = True | Right : Natural >"
> { Left, Right }: Left true
Also, all Dhall expressions are normalized before translation to Nix:
> $ dhall-to-nix <<< "True == False"
> false
You can use the @dhall-to-nix@ executable within Nix to assemble Nix
expressions from Dhall expressions using the following @dhallToNix@ utility
function:
> dhallToNix = code :
> let
> file = builtins.toFile "dhall-expr" code;
>
> drv = pkgs.stdenv.mkDerivation {
> name = "dhall-expr-as-nix";
>
> buildCommand = ''
> dhall-to-nix <<< "${file}" > $out
> '';
>
> buildInputs = [ pkgs.haskellPackages.dhall-nix ];
> };
> in
> import "${drv}";
-}
module Dhall.Nix (
-- * Dhall to Nix
dhallToNix
-- * Exceptions
, CompileError(..)
) where
import Control.Applicative (empty)
import Control.Exception (Exception)
import Data.Foldable (toList)
import Data.Fix (Fix(..))
import Data.Traversable (for)
import Data.Typeable (Typeable)
import Dhall.Core (Chunks(..), Const(..), Expr(..), Var(..))
import Dhall.TypeCheck (X(..))
import Nix.Atoms (NAtom(..))
import Nix.Expr
( Antiquoted(..)
, Binding(..)
, NBinaryOp(..)
, NExprF(..)
, NKeyName(..)
, NString(..)
, Params(..)
, (@@)
, (==>)
, ($+)
)
import qualified Data.Text
import qualified Dhall.Core
import qualified Dhall.Map
import qualified NeatInterpolation
import qualified Nix
{-| This is the exception type for all possible errors that might arise when
translating the Dhall syntax tree to the Nix syntax tree
-}
data CompileError
= CannotReferenceShadowedVariable Var
-- ^ Nix does not provide a way to reference a shadowed variable
deriving (Typeable)
instance Show CompileError where
show (CannotReferenceShadowedVariable v) =
Data.Text.unpack [NeatInterpolation.text|
$_ERROR: Cannot reference shadowed variable
Explanation: Whenever you introduce two variables of the same name, the latter
variable takes precedence:
This x ...
λ(x : Text) λ(x : Text) x
... refers to this x
The former variable is "shadowed":
λ(x : Text) λ(x : Text) x
This x is shadowed
... and Dhall lets you reference shadowed variables using the @ notation:
This x ...
λ(x : Text) λ(x : Text) x@1
... now refers to this x
However, the Nix language does not let you reference shadowed variables and
there is nothing analogous to @ in Nix
Your code contains the following expression:
$txt
... which references a shadowed variable and therefore cannot be translated to
Nix
|]
where
txt = Dhall.Core.pretty v
_ERROR :: Data.Text.Text
_ERROR = "\ESC[1;31mError\ESC[0m"
instance Exception CompileError
{-| Convert a Dhall expression to the equivalent Nix expression
>>> :set -XOverloadedStrings
>>> dhallToNix (Lam "x" Natural (Lam "y" Natural (NaturalPlus "x" "y")))
Right (NAbs (Param "x") (NAbs (Param "y") (NBinary NPlus (NSym "x") (NSym "y"))))
>>> fmap Nix.Pretty.prettyNix it
Right x: y: x + y
Precondition: You must first type-check the Dhall expression before passing
the expression to `dhallToNix`
-}
dhallToNix :: Expr s X -> Either CompileError (Fix NExprF)
dhallToNix e = loop (Dhall.Core.normalize e)
where
loop (Const _) = return (Fix (NSet []))
loop (Var (V a 0)) = return (Fix (NSym a))
loop (Var a ) = Left (CannotReferenceShadowedVariable a)
loop (Lam a _ c) = do
c' <- loop c
return (Fix (NAbs (Param a) c'))
loop (Pi _ _ _) = return (Fix (NSet []))
-- None needs a type to convert to an Optional
loop (App None _) = do
return (Fix (NConstant NNull))
loop (App a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NApp a' b'))
loop (Let as b) = do
as' <- for as $ \a -> do
val <- loop $ Dhall.Core.value a
pure $ NamedVar [StaticKey $ Dhall.Core.variable a] val Nix.nullPos
b' <- loop b
return (Fix (NLet (toList as') b'))
loop (Annot a _) = loop a
loop Bool = return (Fix (NSet []))
loop (BoolLit b) = return (Fix (NConstant (NBool b)))
loop (BoolAnd a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NAnd a' b'))
loop (BoolOr a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NOr a' b'))
loop (BoolEQ a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NEq a' b'))
loop (BoolNE a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NNEq a' b'))
loop (BoolIf a b c) = do
a' <- loop a
b' <- loop b
c' <- loop c
return (Fix (NIf a' b' c'))
loop Natural = return (Fix (NSet []))
loop (NaturalLit n) = return (Fix (NConstant (NInt (fromIntegral n))))
loop NaturalFold = do
let e0 = Fix (NBinary NMinus "n" (Fix (NConstant (NInt 1))))
let e1 = Fix (NBinary NApp (Fix (NBinary NApp (Fix (NBinary NApp "naturalFold" e0)) "t")) "succ")
let e2 = Fix (NBinary NApp "succ" (Fix (NBinary NApp e1 "zero")))
let e3 = Fix (NBinary NLte "n" (Fix (NConstant (NInt 0))))
let e4 = Fix (NAbs "succ" (Fix (NAbs "zero" (Fix (NIf e3 "zero" e2)))))
let e5 = Fix (NAbs "n" (Fix (NAbs "t" e4)))
return (Fix (NLet [NamedVar ["naturalFold"] e5 Nix.nullPos] "naturalFold"))
loop NaturalBuild = do
let e0 = Fix (NBinary NPlus "n" (Fix (NConstant (NInt 1))))
let e1 = Fix (NBinary NApp (Fix (NBinary NApp "k" (Fix (NSet [])))) (Fix (NAbs "n" e0)))
return (Fix (NAbs "k" (Fix (NBinary NApp e1 (Fix (NConstant (NInt 0)))))))
loop NaturalIsZero = do
let e0 = Fix (NBinary NEq "n" (Fix (NConstant (NInt 0))))
return (Fix (NAbs "n" e0))
loop NaturalEven = do
let e0 = Fix (NBinary NMinus "n" (Fix (NConstant (NInt 2))))
let e1 = Fix (NBinary NApp "naturalEven" e0)
let e2 = Fix (NBinary NNEq "n" (Fix (NConstant (NInt 1))))
let e3 = Fix (NBinary NEq "n" (Fix (NConstant (NInt 0))))
let e4 = Fix (NBinary NOr e3 (Fix (NBinary NAnd e2 e1)))
let e5 = NamedVar ["naturalEven"] (Fix (NAbs "n" e4)) Nix.nullPos
let e6 = Fix (NBinary NMinus (Fix (NConstant (NInt 0))) "n")
let e7 = Fix (NBinary NLte "n" (Fix (NConstant (NInt 0))))
let e8 = Fix (NAbs "n" (Fix (NBinary NApp "naturalEven" (Fix (NIf e7 e6 "n")))))
return (Fix (NLet [e5] e8))
loop NaturalOdd = do
let e0 = Fix (NBinary NMinus "n" (Fix (NConstant (NInt 2))))
let e1 = Fix (NBinary NApp "naturalOdd" e0)
let e2 = Fix (NBinary NNEq "n" (Fix (NConstant (NInt 0))))
let e3 = Fix (NBinary NEq "n" (Fix (NConstant (NInt 1))))
let e4 = Fix (NBinary NOr e3 (Fix (NBinary NAnd e2 e1)))
let e5 = NamedVar ["naturalOdd"] (Fix (NAbs "n" e4)) Nix.nullPos
let e6 = Fix (NBinary NMinus (Fix (NConstant (NInt 0))) "n")
let e7 = Fix (NBinary NLte "n" (Fix (NConstant (NInt 0))))
let e8 = Fix (NAbs "n" (Fix (NBinary NApp "naturalOdd" (Fix (NIf e7 e6 "n")))))
return (Fix (NLet [e5] e8))
loop NaturalShow = do
return "toString"
loop NaturalToInteger = do
return (Fix (NAbs "n" "n"))
loop (NaturalPlus a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NPlus a' b'))
loop (NaturalTimes a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NMult a' b'))
loop Integer = return (Fix (NSet []))
loop (IntegerLit n) = return (Fix (NConstant (NInt (fromIntegral n))))
loop IntegerShow = do
let e0 = Fix (NBinary NApp "toString" "x")
let e1 = Fix (NBinary NPlus (Fix (NStr "+")) e0)
let e2 = Fix (NBinary NLte (Fix (NConstant (NInt 0))) "x")
let e3 = Fix (NAbs "x" (Fix (NIf e2 e1 e0)))
return e3
loop IntegerToDouble = do
return (Fix (NAbs "x" "x"))
loop Double = return (Fix (NSet []))
loop (DoubleLit n) = return (Fix (NConstant (NFloat (realToFrac n))))
loop DoubleShow = do
return "toString"
loop Text = return (Fix (NSet []))
loop (TextLit (Chunks abs_ c)) = do
let process (a, b) = do
b' <- loop b
return [Plain a, Antiquoted b']
abs' <- mapM process abs_
let chunks = concat abs' ++ [Plain c]
return (Fix (NStr (DoubleQuoted chunks)))
loop (TextAppend a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NPlus a' b'))
loop TextShow = do
let from =
Nix.mkList
[ Nix.mkStr "\""
, Nix.mkStr "$"
, Nix.mkStr "\\"
-- Nix doesn't support \b and \f
-- , Nix.mkStr "\b"
-- , Nix.mkStr "\f"
, Nix.mkStr "\n"
, Nix.mkStr "\r"
, Nix.mkStr "\t"
]
let to =
Nix.mkList
[ Nix.mkStr "\\\""
, Nix.mkStr "\\u0024"
, Nix.mkStr "\\\\"
-- , Nix.mkStr "\\b"
-- , Nix.mkStr "\\f"
, Nix.mkStr "\\n"
, Nix.mkStr "\\r"
, Nix.mkStr "\\t"
]
let replaced = "builtins.replaceStrings" @@ from @@ to @@ "t"
let quoted = Nix.mkStr "\"" $+ replaced $+ Nix.mkStr "\""
return ("t" ==> quoted)
loop List = return (Fix (NAbs "t" (Fix (NSet []))))
loop (ListAppend a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NConcat a' b'))
loop (ListLit _ bs) = do
bs' <- mapM loop (toList bs)
return (Fix (NList bs'))
loop ListBuild = do
let e0 = Fix (NBinary NApp "k" (Fix (NSet [])))
let e1 = Fix (NBinary NConcat (Fix (NList ["x"])) "xs")
let e2 = Fix (NBinary NApp e0 (Fix (NAbs "x" (Fix (NAbs "xs" e1)))))
let e3 = Fix (NAbs "k" (Fix (NBinary NApp e2 (Fix (NList [])))))
return (Fix (NAbs "t" e3))
loop ListFold = do
let e0 = Fix (NBinary NApp "f" (Fix (NBinary NApp (Fix (NBinary NApp "cons" "y")) "ys")))
let e1 = Fix (NAbs "f" (Fix (NAbs "y" (Fix (NAbs "ys" e0)))))
let e2 = Fix (NBinary NApp "builtins.foldl'" e1)
let e3 = Fix (NBinary NApp (Fix (NBinary NApp e2 (Fix (NAbs "ys" "ys")))) "xs")
let e4 = Fix (NAbs "xs" (Fix (NAbs "t" (Fix (NAbs "cons" e3)))))
return (Fix (NAbs "t" e4))
loop ListLength = return (Fix (NAbs "t" "builtins.length"))
loop ListHead = do
let e0 = Fix (NBinary NApp "builtins.head" "xs")
let e1 = Fix (NBinary NEq "xs" (Fix (NList [])))
let e2 = Fix (NAbs "xs" (Fix (NIf e1 (Fix (NConstant NNull)) e0)))
return (Fix (NAbs "t" e2))
loop ListLast = do
let e0 = Fix (NBinary NApp "builtins.length" "xs")
let e1 = Fix (NBinary NMinus e0 (Fix (NConstant (NInt 1))))
let e2 = Fix (NBinary NApp (Fix (NBinary NApp "builtins.elemAt" "xs")) e1)
let e3 = Fix (NBinary NEq "xs" (Fix (NList [])))
let e4 = Fix (NAbs "xs" (Fix (NIf e3 (Fix (NConstant NNull)) e2)))
return (Fix (NAbs "t" e4))
loop ListIndexed = do
let e0 = Fix (NBinary NApp "builtins.length" "xs")
let e1 = Fix (NBinary NApp (Fix (NBinary NApp "builtins.elemAt" "xs")) "i")
let e2 =
[ NamedVar ["index"] "i" Nix.nullPos
, NamedVar ["value"] e1 Nix.nullPos
]
let e3 = Fix (NBinary NApp "builtins.genList" (Fix (NAbs "i" (Fix (NSet e2)))))
return (Fix (NAbs "t" (Fix (NAbs "xs" (Fix (NBinary NApp e3 e0))))))
loop ListReverse = do
let e0 = Fix (NBinary NMinus "n" "i")
let e1 = Fix (NBinary NMinus e0 (Fix (NConstant (NInt 1))))
let e2 = Fix (NBinary NApp (Fix (NBinary NApp "builtins.elemAt" "xs")) e1)
let e3 = Fix (NBinary NApp "builtins.genList" (Fix (NAbs "i" e2)))
let e4 = Fix (NBinary NApp e3 "n")
let e5 = Fix (NBinary NApp "builtins.length" "xs")
let e6 = Fix (NAbs "xs" (Fix (NLet [NamedVar ["n"] e5 Nix.nullPos] e4)))
return (Fix (NAbs "t" e6))
loop Optional = return (Fix (NAbs "t" (Fix (NSet []))))
loop (OptionalLit _ b) =
case b of
Nothing -> return (Fix (NConstant NNull))
Just c -> loop c
loop (Some a) = loop a
loop None = return (Fix (NConstant NNull))
loop OptionalFold = do
let e0 = Fix (NBinary NEq "x" (Fix (NConstant NNull)))
let e1 = Fix (NIf e0 "nothing" (Fix (NBinary NApp "just" "x")))
let e2 = Fix (NAbs "t" (Fix (NAbs "just" (Fix (NAbs "nothing" e1)))))
return (Fix (NAbs "t" (Fix (NAbs "x" e2))))
loop OptionalBuild = do
let e0 = Pi "nothing" "optional" "optional"
let e1 = Pi "just" (Pi "_" "a" "optional") e0
let e2 = Pi "optional" (Const Type) e1
let e3 = OptionalLit "a" empty
let e4 = Lam "x" "a" (OptionalLit "a" (pure "x"))
let e5 = App (App (App "f" (App Optional "a")) e4) e3
loop (Lam "a" (Const Type) (Lam "f" e2 e5))
loop (Record _) = return (Fix (NSet []))
loop (RecordLit a) = do
a' <- traverse loop a
let a'' = do
(k, v) <- Dhall.Map.toList a'
return (NamedVar [StaticKey k] v Nix.nullPos)
return (Fix (NSet a''))
loop (Union _) = return (Fix (NSet []))
loop (UnionLit k v kts) = do
v' <- loop v
let e0 = do
k' <- k : Dhall.Map.keys kts
return (k', Nothing)
let e2 = Fix (NBinary NApp (Fix (NSym k)) v')
return (Fix (NAbs (ParamSet e0 False Nothing) e2))
loop (Combine a b) = do
a' <- loop a
b' <- loop b
let e0 = Fix (NBinary NApp (Fix (NBinary NApp "map" "toKeyVals")) "ks")
let e1 = Fix (NBinary NApp "builtins.concatLists" e0)
let e2 = Fix (NBinary NApp "builtins.listToAttrs" e1)
let defL = Fix (NBinary NApp (Fix (NBinary NApp "builtins.hasAttr" "k")) "kvsL")
let defR = Fix (NBinary NApp (Fix (NBinary NApp "builtins.hasAttr" "k")) "kvsR")
let valL = Fix (NBinary NApp (Fix (NBinary NApp "builtins.getAttr" "k")) "kvsL")
let valR = Fix (NBinary NApp (Fix (NBinary NApp "builtins.getAttr" "k")) "kvsR")
let empty_ = Fix (NList [])
let toNameValue v =
let bindings =
[ NamedVar ["name" ] "k" Nix.nullPos
, NamedVar ["value"] v Nix.nullPos
]
in Fix (NList [Fix (NSet bindings)])
let e3 = Fix (NBinary NApp (Fix (NBinary NApp "combine" valL)) valR)
let e4 = Fix (NBinary NApp "builtins.isAttrs" valL)
let e5 = Fix (NBinary NApp "builtins.isAttrs" valR)
let e6 = Fix (NBinary NAnd e4 e5)
let e7 = Fix (NIf e6 (toNameValue e3) (toNameValue valR))
let e8 = Fix (NIf defR e7 (toNameValue valL))
let e9 = Fix (NIf defR (toNameValue valR) empty_)
let toKeyVals = Fix (NAbs "k" (Fix (NIf defL e8 e9)))
let ksL = Fix (NBinary NApp "builtins.attrNames" "kvsL")
let ksR = Fix (NBinary NApp "builtins.attrNames" "kvsR")
let ks = Fix (NBinary NConcat ksL ksR)
let e10 =
[ NamedVar ["ks" ] ks Nix.nullPos
, NamedVar ["toKeyVals"] toKeyVals Nix.nullPos
]
let combine = Fix (NAbs "kvsL" (Fix (NAbs "kvsR" (Fix (NLet e10 e2)))))
let e11 = Fix (NBinary NApp (Fix (NBinary NApp "combine" a')) b')
return (Fix (NLet [NamedVar ["combine"] combine Nix.nullPos] e11))
loop (CombineTypes _ _) = return (Fix (NSet []))
loop (Merge a b _) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NApp b' a'))
loop (Prefer a b) = do
a' <- loop a
b' <- loop b
return (Fix (NBinary NUpdate a' b'))
loop (Field a b) = do
a' <- loop a
return (Fix (NSelect a' [StaticKey b] Nothing))
loop (Project a b) = do
a' <- loop a
let b' = fmap StaticKey (toList b)
return (Fix (NSet [Inherit (Just a') b' Nix.nullPos]))
loop (ImportAlt a _) = loop a
loop (Note _ b) = loop b
loop (Embed (X x)) = x