v0.11.0
This release includes several breaking changes, in preparation for the 1.0 release, as well as many enhancements and bug fixes.
Most users will probably want to wait until all aspects of the release have been finalized. Progress on libraries and tools is being tracked here.
Many thanks to the contributors who helped with this release!
Breaking Changes
=>
now acts like a binary type operator
It was previously possible to specify many constraints in the same context by
separating them with commas inside parentheses on the left of the =>
:
runFreeT :: ∀ m f. (Functor f, Monad m) => ...
This is no longer allowed. Instead, =>
now acts like a binary operator, with a
constraint on the left and a type on the right. Multiple constraints must be
introduced using currying, as with regular function arguments:
runFreeT :: ∀ m f. Functor f => Monad m => ...
This is in preparation for adding constraint kinds, at which point =>
will become
an actual binary type operator, defined in Prim
.
*
and !
kinds have been removed
The kind symbols *
(for the kind of types) and !
(for the kind of effects) have been
removed from the parser. Instead of *
, use Type
, which is defined in Prim
.
Instead of !
, use Effect
, which can now be imported from Control.Monad.Eff
.
The #
symbol, which is used to construct a row kind, is still supported. We cannot move this kind into Prim
(because it is polykinded, and we do not support kind polymorphism).
One single consolidated executable
The various psc-*
executables have been replaced with a single executable called purs
.
The various subcommands are documented on the --help
page:
bundle Bundle compiled PureScript modules for the browser
compile Compile PureScript source files
docs Generate Markdown documentation from PureScript source files
hierarchy Generate a GraphViz directed graph of PureScript type classes
ide Start or query an IDE server process
publish Generates documentation packages for upload to Pursuit
repl Enter the interactive mode (PSCi)
Wrapper scripts will be provided in the binary distribution.
psc-package
was removed
psc-package
has been removed from the main compiler distribution. It will still
be maintained along with the package sets repo, but will not be bundled with the compiler.
A binary distribution which is compatible with this release is available.
Implicitly discarded values in do
blocks now raise errors
Code which discards the result of a computation in a do
block:
duplicate :: Array a -> Array a
duplicate xs = do
x <- xs
[true, false] -- the result here is discarded
pure x
will now raise an error. The compiler allows values of certain types to be discarded,
based on the Discard
class in Control.Bind
. The only type which can be discarded is
Unit
, but the feature was implemented using a type class to enable support for
alternative preludes.
No more dependency on the Bower executable
In addition to removing psc-package
from the compiler distribution, we have also
removed any explicit dependency on the Bower executable. The compiler will not assume
use of any particular package manager, but will aim to provide generic support for
package managers generally, via command line options and hooks.
purs publish
will continue to use the Bower JSON formats. The bower.json
format
is now referred to as the "manifest file", while the output of bower list --json
,
which is used by purs publish
internally, is referred to as the "resolutions file".
Enhancements
Pattern Guards
In addition to regular guards:
foo x | condition x = ...
the compiler now supports pattern guards, which let the user simultaneously
test a value against a pattern, and bind names to values.
For example, we can apply a function fn
to an argument x
, succeeding only if
fn
returns Just y
for some y
, binding y
at the same time:
bar x | Just y <- fn x = ... -- x and y are both in scope here
Pattern guards can be very useful for expressing certain types of control flow when
using algebraic data types.
HTML Documentation
The --format html
option has been added to purs docs
. The HTML format uses
the Pursuit template, and is very useful for rendering documentation for offline
use.
Here is an example of the generated HTML.
Duplicate Labels
(@paf31)
Row types now support duplicate labels, which can be useful when using the Eff
monad. For example, we could not previously use the catchException
function if
the resulting action also required the EXCEPTION
effect, since otherwise the
type of the inner action would contain a duplicate label.
Rows are now unordered collections (of labels and types) with duplicates. However,
the collection of types for a specific label within a row is ordered.
Conceptually, a row can be thought of as a type-level Map Label (NonEmptyList Type)
.
A type constructor (such as Record
) which takes a row of types as an argument should
define what its meaning is on each row. The meaning of a value of type Record r
is a JavaScript object where the type of the value associated with each label is given
by the head element of the non-empty list of types for that label.
Row Constraints
A new constraint called Union
has been added to Prim
. Union
is a three-way relation between
rows of types, and the compiler will solve it automatically when it is possible to do so.
Union
is a left-biased union of rows which takes into account duplicate labels. If the same label appears in rows l
and r
, and Union l r u
holds, then the label will appear twice in u
.
Union
makes it possible to give a type to the function which merges two records:
merge :: forall r1 r2 r3. Union r1 r2 r3 => Record r1 -> Record r2 -> Record r3
Note that this is a left-biased merge - if the two input record contain a common label, the type of the
label in the result will be taken from the left input.
Patterns in let
expressions
Let expressions and where
clauses can now use binders on the left hand side of
a declaration:
map f xs =
let { head, tail } = uncons xs
in [f head] <> map f tail
Unlike in Haskell, declarations with these patterns cannot appear in dependency cycles, and bound names can only be used in declarations after the one in which they are brought into scope.
Find record accessors in Type Directed Search
Type-directed search will now include results for record accessors. This can
be very useful when working with extensible records with a type-driven programming
workflow.
Other Enhancements
- Add basic usability check and error for ambiguously-typed type class members (@LiamGoodacre)
- Improved skolem escape check (@paf31)
- Fix links to declarations in
Prim
(@hdgarrood) - Emit
_
instead offalse
case forif then else
to improve optimizations (@rightfold) - Add
InvalidDerivedInstance
error to improve errors for derived instances (@paf31) - Make generated code for superclass instances less ugly (@paf31)
- Support polymorphic types in typed binders (@paf31)
- Make file paths relative in error messages (@paf31)
- Improve errors from module sorter (@paf31)
- Improve error for unused type variables (@paf31)
- Include source span in externs file for error reporting purposes (@paf31)
- Improve instance arity errors (@mrkgnao)
purs ide
Features
Improve import parsing
purs ide
now uses a new import parser, which allowspurs ide
to handle any
import section that the compiler would accept correctly. (@kritzcreek)- Parse imports with hanging right paren (@matthewleon)
- Reuses lenient import parsing for the list import command (@kritzcreek)
Don't create the output/ directory if it can't be found
purs ide
will now no longer leave empty output/ directories behind when it is
started in a directory that is not a PureScript project.
Collect type class instances
purs ide
collects instances and stores them with their respective type class.
There's no way to retrieve these yet, but we will extend the protocol soon.
Bug Fixes
- No longer strip trailing dots for Pursuit queries (@kritzcreek)
- Fix #2537 (
psc-ide
shouldn't crash when building a non-existent file) (@kritzcreek) - Fix #2504 (fix a crash related to prematurely closed handles) (@kritzcreek)
- Speed up rebuilding by x2, by rebuilding with open exports asynchronously (@kritzcreek)
- Return operators in
purs ide
imports list (@nwolverson) - Also detect location information for operators (@kritzcreek)
Cleanup
- Removes unnecessary clause in import pretty printing (@kritzcreek)
- Removes the deprecated
--debug
option (@kritzcreek) - Restructure testing to avoid running the server (@kritzcreek)
purs repl
- Add back
.purs-repl
file support (@paf31) - PSCi command changes, add
:clear
(@noraesae) - Declarations no longer require
let
(@noraesae) - Improve CLI error and startup messages (@noraesae)
Bug Fixes
- Changes to help the tail call optimization fire more consistently (@paf31)
- Fix
everythingWithScope
traversal bug #2718 (@paf31) - Errors for open rows in derived instances (@paf31)
- Instantiate types in record literals as necessary (@paf31)
- Fix
Generic
deriving with synonyms (@paf31) - Rebuild modules if necessary when using
--dump-corefn
(@paf31) - Ensure solved type classes are imported (@LiamGoodacre)
- Allow for older Git versions in
purs publish
(@mcoffin) - Fix
purs publish --dry-run
(@hdgarrood) - Exported data constructors can now contain quotes (@LiamGoodacre)
Documentation
- Capitalise *script into *Script (@noraesae)
Performance
- Optimize
keepImp
(@paf31) - Replace
nub
withordNub
(@matthewleon) - Combine inlining optimizations into a single pass (@paf31)
Other
- Add
HasCallStack
to internalError (@alexbiehl) - Use Stackage LTS 8.0 (@noraesae)
- Address Travis timeout issues (@hdgarrood)
- Improve module structure in PSCi test suite (@noraesae)
- Fix the PSCi script (@mrkgnao)
- Include Git commit information in non-release builds (@hdgarrood)
- Add test case for #2756 (@int-index)
- Some code cleanup in the module imports phase (@matthewleon)