diff --git a/README.md b/README.md index ece7d9b1..144d1e2d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ for syntax with binders (think λ-abstraction, let-binding, for-loop, etc.). The underlying representation is based on the IFL 2022 paper by Maclaurin, Radul, and Paszke [«The Foil: Capture-Avoiding Substitution With No Sharp Edges»](https://doi.org/10.1145/3587216.3587224)[^1]. This project extends the foil with patterns, as well as two techniques for free generation of the foil. The details are presented in the paper [«Free Foil: Generating Efficient and Scope-Safe Abstract Syntax»](https://arxiv.org/abs/2405.16384)[^2]. In brief: -1. We introduce [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#t:CoSinkable) typeclass to generalize `NameBinder`s to more complex patterns. +1. We introduce [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#t:CoSinkable) typeclass to generalize `NameBinder`s to more complex patterns. 2. We provide Template Haskell machinery to generate the proper scope-safe AST definitions as well as conversion functions, and helpers for patterns. This approach works particularly well with the code generated by tools like [BNFC](https://bnfc.digitalgrammars.com) or [`BNFC-meta`](https://hackage.haskell.org/package/BNFC-meta). 3. We define a variant of free scoped monads[^3] with the foil instead of nested data types of Bird and Paterson. This approach allows implementing certain functions once for a large class of languages with binders. Here we implement only substitution, but more involved algorithms, such as generic higher-order preunification[^3] should be possible. @@ -32,32 +32,32 @@ The Haskell code is organized into two packages as follows: #### `free-foil` package -- [`Control.Monad.Foil`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html) provides basic definitions for the foil[^1], including safe scopes, sinking, name maps, and scope constraints. In addition to the standard definitions, we contribute +- [`Control.Monad.Foil`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html) provides basic definitions for the foil[^1], including safe scopes, sinking, name maps, and scope constraints. In addition to the standard definitions, we contribute - - [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#t:CoSinkable) class (dual to [`Sinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#t:Sinkable), for patterns that generalize `NameBinder`) - - a general total [`NameMap`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#g:4) which is useful for some implementations (e.g. conversion functions) + - [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#t:CoSinkable) class (dual to [`Sinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#t:Sinkable), for patterns that generalize `NameBinder`) + - a general total [`NameMap`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#g:4) which is useful for some implementations (e.g. conversion functions) - unification of binders, which is useful for efficient α-equivalence implementations -- [`Control.Monad.Foil.TH`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil-TH.html) provides Template Haskell functions that generate scope-safe representation types together with some conversion functions and helpers for patterns. All of this is generated from a raw recursive representation of syntax, that has to be split into 4 types: type of variable identifiers, type of terms, type of scoped terms (to clearly understand which parts get under binders), and type of patterns. +- [`Control.Monad.Foil.TH`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil-TH.html) provides Template Haskell functions that generate scope-safe representation types together with some conversion functions and helpers for patterns. All of this is generated from a raw recursive representation of syntax, that has to be split into 4 types: type of variable identifiers, type of terms, type of scoped terms (to clearly understand which parts get under binders), and type of patterns. -- [`Control.Monad.Foil.Relative`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil-Relative.html) defines a variation of a relative monad typeclass specifcially indexed by scope type variables of kind `S`. This is merely for the demonstration that term type constructors are monads relative to [`Name`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil-Internal.html#t:Name). +- [`Control.Monad.Foil.Relative`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil-Relative.html) defines a variation of a relative monad typeclass specifcially indexed by scope type variables of kind `S`. This is merely for the demonstration that term type constructors are monads relative to [`Name`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil-Internal.html#t:Name). -- [`Control.Monad.Free.Foil`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Free-Foil.html) defines a variation of free scoped (relative) monads relying on the foil for the scope-safe efficient handling of the binders. This module also defines +- [`Control.Monad.Free.Foil`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Free-Foil.html) defines a variation of free scoped (relative) monads relying on the foil for the scope-safe efficient handling of the binders. This module also defines - generic substitution for this generic representation of syntax with binders - generic α-normalization and α-equivalence checks -- [`Control.Monad.Free.Foil.TH`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Free-Foil-TH.html) provides Template Haskell functions that generate helpers specifically for free foil, including the generation of the signature bifunctor, convenient pattern synonyms, conversion helpers, and instances needed to enable general α-equivalence. +- [`Control.Monad.Free.Foil.TH`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Free-Foil-TH.html) provides Template Haskell functions that generate helpers specifically for free foil, including the generation of the signature bifunctor, convenient pattern synonyms, conversion helpers, and instances needed to enable general α-equivalence. #### `lambda-pi` package -- [`Language.LambdaPi.Impl.Foil`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.2/Language-LambdaPi-Impl-Foil.html) defines a simple interpreter for λΠ-calculus with pairs, using the manually constructed scope-safe representation and conversion to and from the raw representation generated by BNFC. +- [`Language.LambdaPi.Impl.Foil`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.3/Language-LambdaPi-Impl-Foil.html) defines a simple interpreter for λΠ-calculus with pairs, using the manually constructed scope-safe representation and conversion to and from the raw representation generated by BNFC. -- [`Language.LambdaPi.Impl.FoilTH`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.2/Language-LambdaPi-Impl-FoilTH.html) defines a simple interpreter for λΠ-calculus with pairs, using Template Haskell to generate a large portion of the code. +- [`Language.LambdaPi.Impl.FoilTH`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.3/Language-LambdaPi-Impl-FoilTH.html) defines a simple interpreter for λΠ-calculus with pairs, using Template Haskell to generate a large portion of the code. -- [`Language.LambdaPi.Impl.FreeFoil`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.2/Language-LambdaPi-Impl-FreeFoil.html) defines a simple interpreter for λΠ-calculus with pairs, using the free foil approach. +- [`Language.LambdaPi.Impl.FreeFoil`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.3/Language-LambdaPi-Impl-FreeFoil.html) defines a simple interpreter for λΠ-calculus with pairs, using the free foil approach. -- [`Language.LambdaPi.Impl.FreeFoilTH`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.2/Language-LambdaPi-Impl-FreeFoilTH.html) defines a simple interpreter for λΠ-calculus with pairs, using the free foil approach together with Template Haskell generation. This implementation has the most automation and generality. +- [`Language.LambdaPi.Impl.FreeFoilTH`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.3/Language-LambdaPi-Impl-FreeFoilTH.html) defines a simple interpreter for λΠ-calculus with pairs, using the free foil approach together with Template Haskell generation. This implementation has the most automation and generality. ### Scala @@ -69,11 +69,11 @@ In Haskell: 1. We do not (yet) generate α-equivalence via Template Haskell or `GHC.Generics`. We do provide a generic α-equivalence functions for `AST sig n`, and demonstrate how to implement the check manually for λΠ-terms using the foil, but in generating this from Template Haskell or using GHC.Generics is left for future work. 2. We do not (yet) demonstrate an implementation of the typechecker for λΠ in these representations. While it is largely straightforward the main non-trivial part is the equality for the Π-types, which relies on the α-equivalence from the previous item. -3. The free foil does not (yet) support patterns, only single-variable binders. While we think it should be sufficient to parametrize [`AST`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Free-Foil.html#t:AST) and [`ScopedAST`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Free-Foil.html#t:ScopedAST) with a `pattern` type constructor (e.g. literally the same [`Pattern`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.2/Language-LambdaPi-Impl-Foil.html#t:Pattern) type used in the foil examples), we did not check if everything generalizes well enough. +3. The free foil does not (yet) support patterns, only single-variable binders. While we think it should be sufficient to parametrize [`AST`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Free-Foil.html#t:AST) and [`ScopedAST`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Free-Foil.html#t:ScopedAST) with a `pattern` type constructor (e.g. literally the same [`Pattern`](https://fizruk.github.io/free-foil/haddock/lambda-pi-0.0.3/Language-LambdaPi-Impl-Foil.html#t:Pattern) type used in the foil examples), we did not check if everything generalizes well enough. 4. We do not (yet) provide strict versions of the foil and free foil here. The benchmarks, however, do implement these variations. 5. We do not (yet) generate pattern synonyms for the foil with Template Haskell, however, this can be done easily, similarly to [this implementation](https://github.com/rzk-lang/rzk/blob/013b4126adeefe69dc757e38e18cd17a79b5a0fc/rzk/src/Free/Scoped/TH.hs) for free scoped monad. -6. We derive [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#t:CoSinkable) and [`Sinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil.html#t:Sinkable) instances via Template Haskell at the moment. However, a safer and more flexible derivation should be possible via `GHC.Generics`. -7. Many functions, including [`rbind`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.2/Control-Monad-Foil-Relative.html#v:rbind) take in an extra argument of type `Scope n`, which is meant to be the runtime counterpart of the (phantom) type parameter `n :: S`. It might be possible to use [`singletons`](https://hackage.haskell.org/package/singletons) or a similar technique to avoid explicit passing of this argument, making the interface somewhat cleaner. However, since this would change the interface a lot, we do not plan on implementing this approach here. +6. We derive [`CoSinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#t:CoSinkable) and [`Sinkable`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil.html#t:Sinkable) instances via Template Haskell at the moment. However, a safer and more flexible derivation should be possible via `GHC.Generics`. +7. Many functions, including [`rbind`](https://fizruk.github.io/free-foil/haddock/free-foil-0.0.3/Control-Monad-Foil-Relative.html#v:rbind) take in an extra argument of type `Scope n`, which is meant to be the runtime counterpart of the (phantom) type parameter `n :: S`. It might be possible to use [`singletons`](https://hackage.haskell.org/package/singletons) or a similar technique to avoid explicit passing of this argument, making the interface somewhat cleaner. However, since this would change the interface a lot, we do not plan on implementing this approach here. 8. Dealing with scopes generically might enable generic delayed substitution, which plays a big part in normalization by evaluation (NbE) algorithms (which outperform naïve substitution-based evaluation). It should be possible to provide a generic framework for closures of scoped terms and delayed substitutions, but we have not yet investigated that fully. [^1]: Dougal Maclaurin, Alexey Radul, and Adam Paszke. 2023. _The Foil: Capture-Avoiding Substitution With No Sharp Edges._ In Proceedings of the 34th Symposium on Implementation and Application of Functional Languages (IFL '22). Association for Computing Machinery, New York, NY, USA, Article 8, 1–10. diff --git a/haskell/free-foil/ChangeLog.md b/haskell/free-foil/ChangeLog.md index e7cb619a..f9088750 100644 --- a/haskell/free-foil/ChangeLog.md +++ b/haskell/free-foil/ChangeLog.md @@ -1,5 +1,24 @@ # CHANGELOG for `free-foil` +# 0.0.3 — 2024-06-20 + +- Add α-equivalence checks and α-normalization (see [#12](https://github.com/fizruk/free-foil/pull/12)): + + - `Control.Monad.Foil` now offers more helpers to work with binder renaming and binder unification. + These helpers can be used to implement (efficient) α-equivalence. + - In `Control.Monad.Free.Foil` general implementation of α-equivalence and α-normalization is provided. + +- Add general conversion functions for free foil (see [#14](https://github.com/fizruk/free-foil/pull/14)): + + - `Control.Monad.Free.Foil` now offers `convertToAST` and `convertFromAST` functions + enabling easier implementation of conversions raw and scope-safe representations. + +- Add Template Haskell functions for free foil (see [#14](https://github.com/fizruk/free-foil/pull/14)): + + - `Control.Monad.Free.Foil.TH` contains many useful functions to generate free foil from + a raw representation (e.g. generated via BNFC), including generation of the signature, + convenient pattern synonyms, `ZipMatch` instance, and conversion helpers. + # 0.0.2 — 2024-06-18 - Improve TH to support parametrized data types (see [#11](https://github.com/fizruk/free-foil/pull/11)) diff --git a/haskell/free-foil/free-foil.cabal b/haskell/free-foil/free-foil.cabal index e8aac595..db82916b 100644 --- a/haskell/free-foil/free-foil.cabal +++ b/haskell/free-foil/free-foil.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: free-foil -version: 0.0.2 +version: 0.0.3 synopsis: Efficient Type-Safe Capture-Avoiding Substitution for Free (Scoped Monads) description: Please see the README on GitHub at category: Parsing diff --git a/haskell/free-foil/package.yaml b/haskell/free-foil/package.yaml index e3d8eb94..b29155fc 100644 --- a/haskell/free-foil/package.yaml +++ b/haskell/free-foil/package.yaml @@ -1,5 +1,5 @@ name: free-foil -version: 0.0.2 +version: 0.0.3 github: "fizruk/free-foil" license: BSD3 author: "Nikolai Kudasov" diff --git a/haskell/lambda-pi/lambda-pi.cabal b/haskell/lambda-pi/lambda-pi.cabal index 2dde7a6f..5aa9d9c0 100644 --- a/haskell/lambda-pi/lambda-pi.cabal +++ b/haskell/lambda-pi/lambda-pi.cabal @@ -5,7 +5,7 @@ cabal-version: 1.24 -- see: https://github.com/sol/hpack name: lambda-pi -version: 0.0.2 +version: 0.0.3 synopsis: λΠ-calculus implemented in a few different ways. description: Please see the README on GitHub at category: Language @@ -60,7 +60,7 @@ library , bifunctors , containers , deepseq - , free-foil >=0.0.2 + , free-foil >=0.0.3 , template-haskell , text >=1.2.3.1 default-language: Haskell2010 @@ -83,7 +83,7 @@ executable lambda-pi , bifunctors , containers , deepseq - , free-foil >=0.0.2 + , free-foil >=0.0.3 , lambda-pi , template-haskell , text >=1.2.3.1 @@ -108,7 +108,7 @@ test-suite doctests , containers , deepseq , doctest-parallel - , free-foil >=0.0.2 + , free-foil >=0.0.3 , lambda-pi , template-haskell , text >=1.2.3.1 @@ -136,7 +136,7 @@ test-suite spec , bifunctors , containers , deepseq - , free-foil >=0.0.2 + , free-foil >=0.0.3 , hspec , hspec-discover , lambda-pi diff --git a/haskell/lambda-pi/package.yaml b/haskell/lambda-pi/package.yaml index 2bf9b107..1b4be8b2 100644 --- a/haskell/lambda-pi/package.yaml +++ b/haskell/lambda-pi/package.yaml @@ -1,5 +1,5 @@ name: lambda-pi -version: 0.0.2 +version: 0.0.3 github: "fizruk/free-foil" license: BSD3 author: "Nikolai Kudasov" @@ -39,7 +39,7 @@ dependencies: bifunctors: template-haskell: deepseq: - free-foil: ">= 0.0.2" + free-foil: ">= 0.0.3" ghc-options: - -Wall