morte-1.7.1: A bare-bones calculus of constructions

Morte.Import

Contents

Description

Morte lets you import external expressions located either in local files or hosted on network endpoints.

To import a local file as an expression, just insert the path to the file, prepending a ./ if the path is relative to the current directory. For example, suppose we had the following three local files:

-- id
\(a : *) -> \(x : a) -> x
-- Bool
forall (Bool : *) -> forall (True : Bool) -> forall (False : Bool) -> Bool
-- True
\(Bool : *) -> \(True : Bool) -> \(False : Bool) -> True

You could then reference them within a Morte expression using this syntax:

./id ./Bool ./True

... which would embed their expressions directly within the syntax tree:

-- ... expands out to:
(\(a : *) -> \(x : a) -> x)
(forall (Bool : *) -> forall (True : Bool) -> forall (False : Bool) -> True)
(\(Bool : *) -> \(True : Bool) -> \(False : Bool) -> True)

... and which normalizes to:

λ(Bool : *) → λ(True : Bool) → λ(False : Bool) → True

Imported expressions may contain imports of their own, too, which will continue to be resolved. However, Morte will prevent cyclic imports. For example, if you had these two files:

-- foo
./bar
-- bar
./foo

... Morte would throw the following exception if you tried to import foo:

morte:
⤷ ./foo
⤷ ./bar
Cyclic import: ./foo

You can also import expressions hosted on network endpoints. Just use the URL

http://host[:port]/path

The compiler expects the downloaded expressions to be in the same format as local files, specifically UTF8-encoded source code text.

For example, if our id expression were hosted at http://example.com/id, then we would embed the expression within our code using:

http://example.com/id

You can also reuse directory names as expressions. If you provide a path to a local or remote directory then the compiler will look for a file named @ within that directory and use that file to represent the directory.

Synopsis

# Import

Arguments

 :: Maybe Path Starting path -> Expr Path Expression to resolve -> IO (Expr Void)

Resolve all imports within an expression

By default the starting path is the current directory, but you can override the starting path with a file if you read in the expression from that file

newtype Cycle Source #

An import failed because of a cycle in the import graph

Constructors

 Cycle FieldscyclicImport :: PathThe offending cyclic import
Instances
 Source # Instance detailsDefined in Morte.Import MethodsshowsPrec :: Int -> Cycle -> ShowS #show :: Cycle -> String #showList :: [Cycle] -> ShowS # Source # Instance detailsDefined in Morte.Import Methods

newtype ReferentiallyOpaque Source #

Morte tries to ensure that all expressions hosted on network endpoints are weakly referentially transparent, meaning roughly that any two clients will compile the exact same result given the same URL.

To be precise, a strong interpretaton of referential transparency means that if you compiled a URL you could replace the expression hosted at that URL with the compiled result. Let's term this "static linking". Morte (very intentionally) does not satisfy this stronger interpretation of referential transparency since "statically linking" an expression (i.e. permanently resolving all imports) means that the expression will no longer update if its dependencies change.

In general, either interpretation of referential transparency is not enforceable in a networked context since one can easily violate referential transparency with a custom DNS, but Morte can still try to guard against common unintentional violations. To do this, Morte enforces that a non-local import may not reference a local import.

Local imports are defined as:

• A file
• A URL with a host of localhost or 127.0.0.1

All other imports are defined to be non-local

Constructors

 ReferentiallyOpaque FieldsopaqueImport :: PathThe offending opaque import
Instances
 Source # Instance detailsDefined in Morte.Import Methods Source # Instance detailsDefined in Morte.Import Methods

data Imported e Source #

Extend another exception with the current import stack

Constructors

 Imported FieldsimportStack :: [Path]Imports resolved so far, in reverse ordernested :: eThe nested exception
Instances
 Show e => Show (Imported e) Source # Instance detailsDefined in Morte.Import MethodsshowsPrec :: Int -> Imported e -> ShowS #show :: Imported e -> String #showList :: [Imported e] -> ShowS # Exception e => Exception (Imported e) Source # Instance detailsDefined in Morte.Import Methods