HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Moduledhall-1.42.3Haskell2010

Dhall.DirectoryTree

Implementation of the dhall to-directory-tree subcommand

  • 11 types
  • 6 values
  • Packagedhall-1.42.3
  • Exports18
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceDirectoryTree.hs

Filesystem

2 declarations
valuetoDirectoryTree
  1. :: Bool

    Whether to allow path separators in file names or not

  2. -> FilePath
  3. -> Expr Void Void
  4. -> IO ()
#

Attempt to transform a Dhall record into a directory tree where:

  • Records are translated into directories

  • Maps are also translated into directories

  • Text values or fields are translated into files

  • Optional values are omitted if None

  • There is a more advanced way to construct directory trees using a fixpoint encoding. See the documentation below on that.

For example, the following Dhall record:

{ dir = { `hello.txt` = "Hello\n" }
, `goodbye.txt`= Some "Goodbye\n"
, `missing.txt` = None Text
}

... should translate to this directory tree:

$ tree result
result
├── dir
│   └── hello.txt
└── goodbye.txt

$ cat result/dir/hello.txt
Hello

$ cat result/goodbye.txt
Goodbye

Use this in conjunction with the Prelude's support for rendering JSON/YAML in "pure Dhall" so that you can generate files containing JSON. For example:

let JSON =
      https://prelude.dhall-lang.org/v12.0.0/JSON/package.dhall sha256:843783d29e60b558c2de431ce1206ce34bdfde375fcf06de8ec5bf77092fdef7

in  { `example.json` =
        JSON.render (JSON.array [ JSON.number 1.0, JSON.bool True ])
    , `example.yaml` =
        JSON.renderYAML
          (JSON.object (toMap { foo = JSON.string "Hello", bar = JSON.null }))
    }

... which would generate:

$ cat result/example.json
[ 1.0, true ]

$ cat result/example.yaml
! "bar": null
! "foo": "Hello"

Advanced construction of directory trees

In addition to the ways described above using "simple" Dhall values to construct the directory tree there is one based on a fixpoint encoding. It works by passing a value of the following type to the interpreter:

let User = < UserId : Natural | UserName : Text >

let Group = < GroupId : Natural | GroupName : Text >

let Access =
      { execute : Optional Bool
      , read : Optional Bool
      , write : Optional Bool
      }

let Mode =
      { user : Optional Access
      , group : Optional Access
      , other : Optional Access
      }

let Entry =
      \(content : Type) ->
        { name : Text
        , content : content
        , user : Optional User
        , group : Optional Group
        , mode : Optional Mode
        }

in  forall (tree : Type) ->
    forall  ( make
            : { directory : Entry (List tree) -> tree
              , file : Entry Text -> tree
              }
            ) ->
      List tree

The fact that the metadata for filesystem entries is modeled after the POSIX permission model comes with the unfortunate downside that it might not apply to other systems: There, changes to the metadata (user, group, permissions) might be a no-op and no warning will be issued. This is a leaking abstraction of the unix-compat package used internally.

NOTE: This utility does not take care of type-checking and normalizing the provided expression. This will raise a FilesystemError exception or a DhallErrors exception upon encountering an expression that cannot be converted as-is.

Low-level types and functions

16 declarations
datadata User
#

A user identified either by id or name.

Instances6Eq, Ord, Show, Generic, FromDhall, Rep
datadata Mode (f :: Type -> Type)
#

A filesystem mode. See chmod(1). The parameter is meant to be instantiated by either Identity or Maybe depending on the completeness of the information: * For data read from the filesystem it will be Identity. * For user-supplied data it will be Maybe as we want to be able to set only specific bits.

Constructors

Instances10Eq, Ord, Show, Generic, FromDhall, Rep, …
datadata FilesystemEntry
#
Instances6Eq, Ord, Show, Generic, FromDhall, Rep
datadata Entry a
#

A generic filesystem entry. This type holds the metadata that apply to all entries. It is parametric over the content of such an entry.

Instances6Eq, Ord, Show, Generic, FromDhall, Rep
datadata Group
#

A group identified either by id or name.

Instances6Eq, Ord, Show, Generic, FromDhall, Rep
datadata Access (f :: Type -> Type)
#

The permissions for a subject (usergroupother).

Instances10Eq, Ord, Show, Generic, FromDhall, Rep, …
valuesetFileMode :: FilePath -> FileMode -> IO ()
#

A wrapper around setFileMode. On Windows, it does check the resulting file mode of the file/directory and emits a warning if it doesn't match the desired file mode. On all other OS it is identical to setFileMode as it is assumed to work correctly.

Pretty-print a FileMode. The format is similar to the one ls(1): It is display as three blocks of three characters. The first block are the permissions of the user, the second one are the ones of the group and the third one the ones of other subjects. A r denotes that the file or directory is readable by the subject, a w denotes that it is writable and an x denotes that it is executable. Unset permissions are represented by -.