packages feed

hakyll-dhall (empty) → 0.1.0.0

raw patch · 12 files changed

+640/−0 lines, 12 filesdep +basedep +binarydep +cborgsetup-changed

Dependencies added: base, binary, cborg, containers, data-default-class, dhall, filepath, hakyll, hakyll-dhall, lens-family-core, mtl, prettyprinter, text, transformers

Files

+ CHANGELOG.md view
@@ -0,0 +1,11 @@+Changelog+=========++Version 0.1.0.0+---------------++*October 3, 2018*++<https://github.com/mstksg/backprop/releases/tag/v0.1.0.0>++*   Initial release
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Justin Le (c) 2018++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 Justin Le 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.
+ README.md view
@@ -0,0 +1,21 @@+# [hakyll-dhall][]++[![hakyll-dhall on Hackage](https://img.shields.io/hackage/v/hakyll-dhall.svg?maxAge=86400)](https://hackage.haskell.org/package/hakyll-dhall)+[![Build Status](https://travis-ci.org/mstksg/hakyll-dhall.svg?branch=master)](https://travis-ci.org/mstksg/hakyll-dhall)++[Hakyll][hakyll] compiler and loader for [Dhall][dhall] files.  Functions are+intended to track all local dependencies within the project directory, so+rebuilds are properly triggered on up-stream imports.  Provides options for+customizing rebuilding behavior for network, environment variable, and+non-project local files.++`loadDhall` and `loadDhallExpr` allow for loading and parsing of Dhall files+for usage within the 'Compiler' monad, so you can use the results as+intermediate parts in building your pages.  `parseDhall` allows directly+passing in Dhall strings to parse and resolve, tracking imports.+`dhallCompiler` is meant as a "final end-point", which just pretty-prints a+parsed Dhall file, with optional normalization.++[hakyll-dhall]: http://hackage.haskell.org/package/hakyll-dhall+[hakyll]: http://hackage.haskell.org/package/hakyll+[dhall]: http://hackage.haskell.org/package/dhall
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/test-app.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE OverloadedStrings #-}++import           Dhall+import           Hakyll+import           Hakyll.Web.Dhall++main :: IO ()+main = hakyll $ do+    match "test-dhall/**" $ do+      route idRoute+      compile dhallFullCompiler++    create ["testparse.txt"] $ do+      route idRoute+      compile $ loadDhall (auto :: Type String) "test-dhall/parse-test.dhall"
+ hakyll-dhall.cabal view
@@ -0,0 +1,72 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.30.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 25f480672df6d437301f7a05c8f3999bdc244d13ea7a789df755a6a6419a734c++name:           hakyll-dhall+version:        0.1.0.0+synopsis:       Dhall compiler for Hakyll+description:    Please see the README on GitHub at <https://github.com/mstksg/hakyll-dhall#readme>+category:       Web+homepage:       https://github.com/mstksg/hakyll-dhall#readme+bug-reports:    https://github.com/mstksg/hakyll-dhall/issues+author:         Justin Le+maintainer:     justin@jle.im+copyright:      (c) Justin Le 2018+license:        BSD3+license-file:   LICENSE+tested-with:    GHC >= 8.2 && < 8.8+build-type:     Simple+extra-source-files:+    README.md+    CHANGELOG.md+    test-dhall/foo.dhall+    test-dhall/parse-test.dhall+    test-dhall/test-file.dhall+    test-dhall/test1.dhall+    test-dhall/test2.dhall++source-repository head+  type: git+  location: https://github.com/mstksg/hakyll-dhall++library+  exposed-modules:+      Hakyll.Web.Dhall+  other-modules:+      Paths_hakyll_dhall+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Wredundant-constraints+  build-depends:+      base >=4.7 && <5+    , binary+    , cborg+    , containers+    , data-default-class+    , dhall >1.17+    , filepath+    , hakyll+    , lens-family-core+    , mtl+    , prettyprinter+    , text+    , transformers+  default-language: Haskell2010++executable hakyll-dhall-test-app+  main-is: test-app.hs+  other-modules:+      Paths_hakyll_dhall+  hs-source-dirs:+      app+  ghc-options: -Wall -Wcompat -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , dhall >1.17+    , hakyll+    , hakyll-dhall+  default-language: Haskell2010
+ src/Hakyll/Web/Dhall.hs view
@@ -0,0 +1,477 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE TypeApplications    #-}++-- |+-- Module      : Hakyll.Web.Dhall+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Hakyll compiler and loader for Dhall files.  Functions are intended to+-- track all local dependencies within the project directory, so rebuilds+-- are properly triggered on up-stream imports.  Provides options for+-- customizing rebuilding behavior for network, environment variable, and+-- non-project local files.+--+-- 'loadDhall' and 'loadDhallExpr' allow for loading and parsing of Dhall+-- files for usage within the 'Compiler' monad, so you can use the results+-- as intermediate parts in building your pages.  'parseDhall' allows+-- directly passing in Dhall strings to parse and resolve, tracking+-- imports.  'dhallCompiler' is meant as a "final end-point", which just+-- pretty-prints a parsed Dhall file, with optional normalization.+++module Hakyll.Web.Dhall (+  -- * Configuration and Options+    DhallCompilerOptions(..), DhallCompilerTrust(..)+  , defaultDhallCompilerOptions, dcoResolver, dcoMinimize, dcoNormalize+  -- ** Resolver Behaviors+  , DhallResolver(..), DefaultDhallResolver(..), drRemap, drFull+  -- * Load Dhall Files+  -- ** As as custom Haskell types+  , loadDhall, loadDhallWith+  -- ** As raw expressions+  , loadDhallExpr, loadDhallExprWith+  , DExpr(..)+  -- * Parse raw Dhall expressions+  , parseDhall, parseDhallWith+  -- * Compile (prettify, normalize, re-map) Dhall Files+  , dhallCompiler+  , dhallRawCompiler, dhallFullCompiler+  , dhallCompilerWith+  -- * Internal Utilities+  , parseRawDhallWith+  , resolveDhallImports+  ) where++import           Control.Monad+import           Control.Monad.Error.Class+import           Control.Monad.IO.Class+import           Control.Monad.Trans.State.Strict+import           Data.Default.Class+import           Data.IORef+import           Data.Maybe+import           Data.Typeable                         (Typeable)+import           Dhall hiding                          (maybe)+import           Dhall.Binary+import           Dhall.Core+import           Dhall.Diff+import           Dhall.Import+import           Dhall.Parser+import           Dhall.Pretty+import           Dhall.TypeCheck+import           GHC.Generics                          (Generic)+import           Hakyll.Core.Compiler+import           Hakyll.Core.Compiler.Internal+import           Hakyll.Core.Dependencies+import           Hakyll.Core.Identifier+import           Hakyll.Core.Item+import           Hakyll.Core.Writable+import           Lens.Family                           (LensLike, LensLike', (.~), (&))+import           System.FilePath+import           System.IO+import qualified Codec.CBOR.Read                       as CBOR+import qualified Codec.CBOR.Term                       as CBOR+import qualified Codec.CBOR.Write                      as CBOR+import qualified Data.Binary                           as Bi+import qualified Data.Binary.Get                       as Bi+import qualified Data.Binary.Put                       as Bi+import qualified Data.Kind                             as K+import qualified Data.Set                              as S+import qualified Data.Text                             as T+import qualified Data.Text.Prettyprint.Doc             as PP+import qualified Data.Text.Prettyprint.Doc.Render.Text as PP++-- | Newtype wrapper over @'Expr' 'Src' a@ (A Dhall expression) with an+-- appropriate 'Bi.Binary' instance, meant to be usable as a compilable+-- Hakyll result that can be saved with 'saveSnapshot', 'load', etc.+newtype DExpr a = DExpr { getDExpr :: Expr Src a }+    deriving (Generic, Typeable)++instance (DefaultDhallResolver a, PP.Pretty a) => Bi.Binary (DExpr a) where+    put = Bi.putBuilder+        . CBOR.toBuilder+        . CBOR.encodeTerm+        . encode V_1_0+        . fmap toImport+        . getDExpr+      where+        toImport = case defaultDhallResolver @a of+                     DRRaw  _ -> id+                     DRFull _ -> absurd+    get = do+        bs     <- Bi.getRemainingLazyByteString+        (_, t) <- either (fail . show) pure $+                    CBOR.deserialiseFromBytes CBOR.decodeTerm bs+        e      <- either (fail . show) pure $+                    decode t+        DExpr <$> traverse fromImport e+      where+        fromImport i = case defaultDhallResolver @a of+          DRRaw  _ -> pure i+          DRFull _ -> fail $+            "Unexpected import in deserialization of `DExpr X`: "+              ++ T.unpack (iStr i)+        iStr = PP.renderStrict+             . PP.layoutSmart layoutOpts+             . PP.pretty @Import++-- | Automatically "pretty prints" in multi-line form+instance PP.Pretty a => Writable (DExpr a) where+    write fp e = withFile fp WriteMode $ \h ->+      PP.renderIO h+        . PP.layoutSmart layoutOpts+        . PP.unAnnotate+        . prettyExpr+        . getDExpr+        . itemBody+        $ e++-- | Types of external imports that a Dhall file may have.+data DhallCompilerTrust = DCTLocal+                            -- ^ File on local filesystem outside of+                            -- project directory, and therefore not tracked+                            -- by Hakyll+                        | DCTRemote+                            -- ^ Link to remote resource over a network+                            -- connection+                        | DCTEnv+                            -- ^ Reference to environment variable on+                            -- machine+  deriving (Generic, Typeable, Show, Eq, Ord)++-- | Options for loading Dhall files.+data DhallCompilerOptions a = DCO+    { _dcoResolver :: DhallResolver a+      -- ^ Method to resolve imports encountered in files.  See+      -- documentation of 'DhallResolver' for more details.+    , _dcoMinimize :: Bool+      -- ^ Strictly for usage with 'dhallCompiler' and family: should the+      -- result be "minimized" (all in one line) or pretty-printed for+      -- human readability?+      --+      -- Can be useful for saving bandwidth.+      --+      -- Default: 'False'+    , _dcoNormalize :: Bool+      -- ^ If 'True', reduce expressions to normal form before using+      -- them.  Otherwise, attempts to do no normalization and presents+      -- the file as-is (stripping out comments and annotations)+      --+      -- Default: 'True'+    }+  deriving (Generic, Typeable)++-- | Lens for '_dcoResolver' field of 'DhallCompilerOptions'.+dcoResolver+    :: Functor f+    => LensLike f (DhallCompilerOptions a) (DhallCompilerOptions b) (DhallResolver a) (DhallResolver b)+dcoResolver f (DCO r m n) = (\r' -> DCO r' m n) <$> f r++-- | Lens for '_dcoMinimize' field of 'DhallCompilerOptions'.+dcoMinimize+    :: Functor f+    => LensLike' f (DhallCompilerOptions a) Bool+dcoMinimize f (DCO r m n) = (\m' -> DCO r m' n) <$> f m++-- | Lens for '_dcoNormalize' field of 'DhallCompilerOptions'.+dcoNormalize+    :: Functor f+    => LensLike' f (DhallCompilerOptions a) Bool+dcoNormalize f (DCO r m n) = DCO r m <$> f n++-- | Method for resolving imports.+--+-- The choice will determine the type of expression that 'loadDhallExpr'+-- and family will produce.+--+-- Note that at this moment, the only available options are "all or+-- nothing" --- either resolve all types imports completely and fully, or+-- none of them. Hopefully one day this library will offer the ability to+-- resolve only certain types of imports (environment variables, absolute+-- paths) and not others (remote network, local paths).+data DhallResolver :: K.Type -> K.Type where+    -- | Leave imports as imports, but optionally remap the destinations.+    DRRaw  :: { _drRemap :: Import -> Compiler (Expr Src Import)+                -- ^ Optionally remap the destinations.+                --+                -- __Important:__ '_drRemap' is /not/ applied recursively;+                -- it is only applied once.  Any imports in the resulting+                -- 'Expr Src Import' are not re-expanded.+                --+                -- Default: leave imports unchanged+              } -> DhallResolver Import+    -- | Completely resolve all imports in IO.  All imports within Hakyll+    -- project are tracked, and changes to dependencies will trigger+    -- rebuilds upstream.+    DRFull :: { _drTrust :: S.Set DhallCompilerTrust+                -- ^ Set of "trusted" import behaviors.  Files with+                -- external references or imports that aren't described in+                -- this set are always rebuilt every time.+                --+                -- Default: @'S.singleton' 'DCTRemote'@+                --+                -- That is, do not trust any dependencies on the local disk+                -- outside of the project directory, but trust that any URL+                -- imports remain unchanged.+              } -> DhallResolver X++-- | Lens for '_drRemap' field of 'DhallResolver'.+drRemap+    :: Functor f+    => LensLike' f (DhallResolver Import) (Import -> Compiler (Expr Src Import))+drRemap f (DRRaw r) = DRRaw <$> f r++-- | Lens for '_drFull' field of 'DhallResolver'.+drFull+    :: Functor f+    => LensLike' f (DhallResolver X) (S.Set DhallCompilerTrust)+drFull f (DRFull t) = DRFull <$> f t++-- | Default 'DhallCompilerOptions'.  If the type variable is not+-- inferrable, it can be helpful to use /TypeApplications/ syntax:+--+-- @+-- 'defaultCompilerOptions' \@'Import'         -- do not resolve imports+-- 'defaultCompilerOptions' \@'X'              -- resolve imports+-- @+defaultDhallCompilerOptions+    :: DefaultDhallResolver a+    => DhallCompilerOptions a+defaultDhallCompilerOptions = DCO+    { _dcoResolver  = defaultDhallResolver+    , _dcoMinimize  = False+    , _dcoNormalize = True+    }++-- | Helper typeclass to allow functions to be polymorphic over different+-- 'DhallResolver' types.+--+-- Provides default behavior for each resolver type.+class DefaultDhallResolver a where+    defaultDhallResolver :: DhallResolver a++-- | Leave all imports unchanged+instance DefaultDhallResolver Import where+    defaultDhallResolver = DRRaw $ pure . Embed++-- | Only trust remote imports remain unchanged.  Rebuild every time if any+-- absolute, home-directory-based, or environment variable imports are in+-- file.+instance DefaultDhallResolver X where+    defaultDhallResolver = DRFull $ S.singleton DCTRemote++-- | @'def' = 'defaultDhallCompilerOptions'@+instance DefaultDhallResolver a => Default (DhallCompilerOptions a) where+    def = defaultDhallCompilerOptions++-- TODO: other resolver functions+-- TODO: maybe one day hakyll can track environment variables?++-- | Essentially a Dhall pretty-printer, (optional) normalizer, and+-- re-formatter.  Compile the Dhall file as text according to default+-- 'DhallCompilerOptions'.  Note that this is polymorphic over both "raw"+-- and "fully resolved" versions; it must be called with+-- /TypeApplications/.+--+-- @+-- 'dhallRawCompiler'  = 'dhallCompiler' \@'Import'+-- 'dhallFullCompiler' = 'dhallCompiler' \@'X'+-- @+--+-- It might be more convenient to just use 'dhallRawCompiler' or+-- 'dhallFullCompiler'.+dhallCompiler+    :: forall a. (DefaultDhallResolver a, PP.Pretty a)+    => Compiler (Item String)+dhallCompiler = dhallCompilerWith @a defaultDhallCompilerOptions++-- TODO: way to only resolve Env and Absolute and Home?+-- Need to somehow hook into 'loadWith' so it can be recursive++-- | Compile the Dhall file as text according to default+-- 'DhallCompilerOptions' while leaving all imports unchanged and+-- unresolved.  Essentially a Dhall pretty-printer, (optional) normalizer,+-- and re-formatter.+dhallRawCompiler :: Compiler (Item String)+dhallRawCompiler = dhallCompilerWith @Import defaultDhallCompilerOptions++-- | Compile the Dhall file as text according to default+-- 'DhallCompilerOptions', resolving all imports in IO and tracking+-- dependencies.  Essentially a Dhall pretty-printer, (optional)+-- normalizer, and re-formatter.+dhallFullCompiler :: Compiler (Item String)+dhallFullCompiler = dhallCompilerWith @X defaultDhallCompilerOptions++-- | 'dhallCompiler', but with custom 'DhallCompilerOptions'.+dhallCompilerWith+    :: PP.Pretty a+    => DhallCompilerOptions a+    -> Compiler (Item String)+dhallCompilerWith dco = do+    i <- getUnderlying+    b <- T.pack . itemBody <$> getResourceBody+    e <- parseDhallWith dco (Just i) b+    makeItem $ T.unpack (disp e)+  where+    disp+      | _dcoMinimize dco = pretty+      | otherwise        = PP.renderStrict+                         . PP.layoutSmart layoutOpts+                         . PP.unAnnotate+                         . prettyExpr++-- | Version of 'parseDhallWith' that only acceps the 'DRRaw' resolver,+-- remapping the imports with the function in the 'DRRaw'.  Does not+-- perform any normalization.+parseRawDhallWith+    :: DhallCompilerOptions Import+    -> Maybe Identifier+    -> T.Text+    -> Compiler (Expr Src Import)+parseRawDhallWith DCO{..} i b =+    case exprFromText (maybe "Raw dhall string" toFilePath i) b of+      Left  e -> throwError . (:[]) $+        "Error parsing raw dhall file: " ++ show e+      Right e -> join <$> traverse (_drRemap _dcoResolver) e++-- | Parse a Dhall source.  Meant to be useful for patterns similar to+-- @dhall-to-text@.  If using examples from+-- <https://github.com/dhall-lang/dhall-text>, you can use:+--+-- @+-- 'parseDhall' 'Nothing' ".\/make-items .\/people"+-- @+--+-- Any local dependencies within the project directory (./make-items and+-- ./people above, for example) are tracked by Hakyll, and so modifications+-- to required files will also cause upstream files to be rebuilt.+parseDhall+    :: DefaultDhallResolver a+    => Maybe Identifier             -- ^ Optional 'Identifier' used to specify directory root for imports+    -> T.Text+    -> Compiler (Expr Src a)+parseDhall = parseDhallWith defaultDhallCompilerOptions++-- | Version of 'parseDhall' taking custom 'DhallCompilerOptions'.+parseDhallWith+    :: DhallCompilerOptions a+    -> Maybe Identifier             -- ^ Optional 'Identifier' used to specify directory root for imports+    -> T.Text+    -> Compiler (Expr Src a)+parseDhallWith dco i b = case _dcoResolver dco of+    DRRaw  _ -> norm <$> parseRawDhallWith dco i b+    DRFull _ -> fmap norm+              . resolveDhallImports dco i+            =<< parseRawDhallWith (dco { _dcoResolver = defaultDhallResolver })+                  i b+  where+    norm :: Eq b => Expr s b -> Expr s b+    norm+      | _dcoNormalize dco = normalize+      | otherwise         = id++-- | Resolve all imports in a parsed Dhall expression.+--+-- This implements the "magic" of dependency tracking: implemented so that+-- any local dependencies within the project directory are tracked by+-- Hakyll, and so modifications to required files will also cause upstream+-- files to be rebuilt.+resolveDhallImports+    :: DhallCompilerOptions X+    -> Maybe Identifier             -- ^ Optional 'Identifier' used to specify directory root for imports+    -> Expr Src Import+    -> Compiler (Expr Src X)+resolveDhallImports DCO{..} ident e = do+    (res, imps) <- unsafeCompiler $ do+      iRef <- newIORef []+      res <- evalStateT (loadWith e) $+        emptyStatus (takeDirectory (maybe "./" toFilePath ident))+          & resolver .~ \i -> do+              liftIO $ modifyIORef iRef (i:)+              exprFromImport i+      (res,) <$> readIORef iRef+    compilerTellDependencies $ mapMaybe mkDep imps+    pure res+  where+    DRFull{..} = _dcoResolver+    mkDep :: Import -> Maybe Dependency+    mkDep i = case importType (importHashed i) of+      Local Here (File (Directory xs) x) -> Just+                                          . IdentifierDependency+                                          . fromFilePath+                                          . joinPath+                                          . map T.unpack+                                          . reverse+                                          $ x : xs+      Local _    _+        | DCTLocal  `S.member` _drTrust -> Nothing+        | otherwise                     -> Just neverTrust+      Remote _+        | DCTRemote `S.member` _drTrust -> Nothing+        | otherwise                     -> Just neverTrust+      Env _+        | DCTEnv    `S.member` _drTrust -> Nothing+        | otherwise                     -> Just neverTrust+      Missing                           -> Just neverTrust+    neverTrust = PatternDependency mempty mempty++-- | Load and parse the body of the given 'Identifier' as a Dhall+-- expression.+--+-- If you wrap the result in 'DExpr', you can save the result as+-- a snapshot.+loadDhallExpr+    :: DefaultDhallResolver a+    => Identifier+    -> Compiler (Item (Expr Src a))+loadDhallExpr = loadDhallExprWith defaultDhallCompilerOptions++-- | Version of 'loadDhallExpr' taking custom 'DhallCompilerOptions'.+loadDhallExprWith+    :: DhallCompilerOptions a+    -> Identifier+    -> Compiler (Item (Expr Src a))+loadDhallExprWith dco i = do+    b <- T.pack <$> loadBody i+    Item i <$> parseDhallWith dco (Just i) b++-- | Load a value of type @a@ that is parsed from a Dhall file at the given+-- 'Identifier'.  Tracks dependencies within project.+loadDhall+    :: Type a+    -> Identifier+    -> Compiler (Item a)+loadDhall = loadDhallWith defaultDhallCompilerOptions++-- | Version of 'loadDhall' taking custom 'DhallCompilerOptions'.+loadDhallWith+    :: DhallCompilerOptions X+    -> Type a+    -> Identifier+    -> Compiler (Item a)+loadDhallWith dco t ident = traverse (inp t)+                        =<< loadDhallExprWith dco ident+  where+    inp :: Type a -> Expr Src X -> Compiler a+    inp t' e = case rawInput t' e of+      Nothing -> throwError . (terr:) . (:[]) $ case typeOf e of+        Left err  -> show err+        Right t0  -> T.unpack+                   . PP.renderStrict+                   . PP.layoutSmart layoutOpts+                   . diffNormalized (expected t)+                   $ t0+      Just x  -> pure x+    terr = "Error interpreting Dhall expression as desired type."
+ test-dhall/foo.dhall view
@@ -0,0 +1,3 @@+[ ./test1.dhall+, ./test2.dhall+]
+ test-dhall/parse-test.dhall view
@@ -0,0 +1,1 @@+"this is a string"
+ test-dhall/test-file.dhall view
@@ -0,0 +1,6 @@+{ foo = ./foo.dhall+, bar = < Hey = {=} | Ho : {} >+, baz = let not = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not+        in  not True+, hi  = ~/local/local-test.dhall+}
+ test-dhall/test1.dhall view
@@ -0,0 +1,1 @@+"hello!"
+ test-dhall/test2.dhall view
@@ -0,0 +1,1 @@+"yo!"