Changelog History
Page 1
-
v0.15.2 Changes
๐ New features:
- Check for partially applied synonyms in kinds, ctors (#4169 by @rhendric)
This check doesn't prevent any programs from compiling; it just makes sure that a more specific
PartiallyAppliedSynonym
error is raised instead of aKindsDoNotUnify
error, which could be interpreted as implying that a partially applied synonym has a valid kind and would be supported elsewhere if that kind is expected.- ๐ Support deriving instances for type synonyms (#4315 by @rhendric)
๐ Bugfixes:
- โ Do not emit warnings about type wildcards used in binders (patterns). (#4309 by @fsoikin)
Type wildcards in the following examples no longer trigger a warning:
f :: Int f = 42 # \(x :: _) -> x g :: Maybe Int g = do x :: _ <- getX pure $ x + 5
๐ Fix issue with unnamed instances using type operators (#4311 by @rhendric)
๐ Fix incorrect
Prim.Int (class Compare)
docs:Int
&Ordering
, notSymbol
(#4313 by @JordanMartinez)๐ Fix bad interaction between module renaming and inliner (#4322 by @rhendric)
This bug was triggered when modules that the compiler handles specially are shadowed by local constructors. For example, a constructor named
Prim
could have caused references toPrim_1["undefined"]
to be produced in the compiled code, leading to a reference error at run time. Less severely, a constructor namedControl_Bind
would have caused the compiler not to inline known monadic functions, leading to slower and less readable compiled code.โก๏ธ Update
Prim
docs for Boolean, Int, String/Symbol, Number, Record, and Row (#4317 by @JordanMartinez)๐ Fix crash caused by polykinded instances (#4325 by @rhendric)
A polykinded instance is a class instance where one or more of the type parameters has an indeterminate kind. For example, the kind of
a
ininstance SomeClass (Proxy a) where ...
is indeterminate unless it's somehow used in a constraint or functional dependency of the instance in a way that determines it.
The above instance would not have caused the crash; instead, instances needed to be of the form
instance SomeClass (f a) where ...
in order to cause it.
- ๐ Fix bad interaction between newtype deriving and type synonyms (#4315 by @rhendric)
See #3453.
- ๐ Fix bad interaction between instance deriving and type synonyms (#4315 by @rhendric)
See #4105.
- ๐ Fix spurious kind unification error triggered by newtype deriving, type synonyms, and polykinds (#4315 by @rhendric)
See #4200.
Internal:
- ๐ Deploy builds continuously to GitHub and npm (#4306 and #4324 by @rhendric)
(Builds triggered by changes that shouldn't affect the published package are not deployed.)
- ๐ Fix incomplete type traversals (#4155 by @rhendric)
This corrects oversights in some compiler internals that are not known to be the cause of any user-facing issues.
- โฌ๏ธ Drop dependency on microlens libraries (#4327 by @rhendric)
-
v0.15.1 Changes
๐ Release skipped; use 0.15.2.
-
v0.15.0 Changes
๐ฅ Breaking changes:
- Switch from Common JS to ES modules (#4232 by @sigma-andex)
Previously, Purescript used Common JS for FFI declarations.
Before, FFI was declared like this...
const mymodule = require('mymodule') exports.myvar = mymodule.myvar
...and will be changed to this...
import * as M from 'mymodule'; export const myvar = M.myvar
...or using the short version...
export { myvar } from 'mymodule';
- FFI is annotated with
/* #__PURE__ */
so that bundlers can perform DCE The current LTS Node.js version
12
is now the required minimum version๐ Improve apartness checking (#4149 by @rhendric)
See details in https://github.com/purescript/documentation/blob/master/language/Type-Classes.md#instance-chains
- Disable type class constraints in FFI (#4240 by @JordanMartinez)
Previously, one could write FFI like the following:
foreign import foo :: forall a. Show a => a -> String
Type class dictionaries are "magically" handled by the compiler. By including them in the above FFI, one can depend on their representation. Since the representation can change without notice, this may silently break code.
In
v0.14.x
, a warning was emitted if these were used. Now it will fail to compile. Rather, one should write something like the following where the members of the type class are passed explicitly to the FFI function as arguments:foo :: forall a. Show a => a -> String foo val = fooImpl show val foreign import fooImpl :: forall a. (a -> String) -> a -> String
โ Removes deprecated syntax for rows (i.e.
#
) and kinds (i.e.kind
-keyword) (#4239 by @JordanMartinez)Apply precedence rules to operator sections (#4033 by @rhendric)
Previously,
(_ * 4 + 1)
would desugar to\x -> x * (4 + 1)
, even though*
has higher precedence than+
. Conversely,(3 * 2 + _)
would not compile, even though*
has higher precedence than+
. These bugs have now been fixed;(_ * 4 + 1)
is an error, and(3 * 2 + _)
desugars to\x -> 3 * 2 + x
.If you have code that relied on the old behavior, add an extra pair of parentheses around the expression in the section.
- ๐ If FFI parsing succeeds & CommonJS is detected, fail; otherwise, do not error or warn (#4250 by @sigma-andex)
Previously, the compiler would emit an error if it failed to parse the FFI JavaScript file. Since the underlying JavaScript parser (i.e.
language-javascript
) fails to parse even valid JavaScript files, we cannot consider every failed parse to mean invalid JS files. Fixing the parser would require a lot of effort, so we are planning to remove it instead inv0.16.x
.If the parse succeeds and a CommonJS module is detected, a compiler error is now emitted. If the parse fails, we no longer emit a compiler error. While we could emit a warning, such a warning will quickly become annoying for FFI files that trigger the buggy paths of
language-javascript
. Moreover, we presume that all will be migrating their code to ES modules now that CommonJS is being deprecated in the larger JavaScript ecosystem.- Warn on ad-hoc non-single-line case expression syntax (#4241 by @JordanMartinez)
The following code will now produce a compiler warning. These were originally supported to ease the migration to the new CST parser.
-- before: `arg` isn't indented "past" the `Foo arg` binder case foo of Foo arg -> arg -- after case foo of Foo arg -> foo
Dropping the above syntax make case expressions more similar to how
let
bindings work:let ok = 1 let ok = 1 let ok = 1 let notOk = 1
- โฌ๏ธ Drop support for browser backend for repl (i.e.
purs repl --port 1234
) (#4255 by @JordanMartinez)
Running this command will print a link that directs users to use Try PureScript instead.
- โ Remove
purs bundle
(#4255 by @JordanMartinez)
Users of
purs bundle
should switch to a standalone bundler such asesbuild
,webpack
orparcel
.- Lazy initialization for recursive bindings (#4283 by @rhendric)
This is unlikely to break a working program, but the upshot for users is that it's now possible to get a run-time error when dereferencing an identifier in a recursive binding group before it has been initialized, instead of silently getting an
undefined
value and having that maybe or maybe not lead to an error somewhere else.This change can cause code that relies on tail-call optimization to no longer compile with that optimization. If you find that code that previously compiled to a TCO loop no longer does but does include
$lazy
initializers, please report the issue.Alternate backend maintainers: for you, this change represents a clarification of a responsibility shared by all backends. The identifiers bound in a recursive binding group need to behave as if those identifiers have call-by-need semantics during the initialization of the entire binding group. (Initializing the binding group entails ensuring every initializer has been executed, so after the binding group is initialized, these identifiers can be considered call-by-value again.)
If an identifier is needed during its own call-by-need initialization, the backend must ensure that an explicit run-time error is raised appropriate for your target platform. This error may be raised at compile time instead if the backend can determine that such a cycle is inevitable. Returning your target language's equivalent of JavaScript's
undefined
, aspurs
did in earlier releases in some cases, is not permitted.If your target language natively has call-by-need semantics, you probably don't have to do anything. If your target language is call-by-value and you are using PureScript as a library, you can use the function
Language.PureScript.CoreFn.Laziness.applyLazinessTransform
to your CoreFn input to satisfy this responsibility; if you do, you will need to do the following:* Translate `InternalIdent RuntimeLazyFactory` and `InternalIdent (Lazy _)` identifiers to appropriate strings for your backend * Ensure that any output file that needs it has a reference to a function named `InternalIdent RuntimeLazyFactory`, with type `forall a. Fn3 String String (Unit -> a) (Int -> a)`, and with the same semantics as the following JavaScript (though you should customize the error raised to be appropriate for your target language): ```js function (name, moduleName, init) { var state = 0; var val; return function (lineNumber) { if (state === 2) return val; if (state === 1) throw new ReferenceError(name + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber); state = 1; val = init(); state = 2; return val; }; }; ```
If neither of the previous cases apply to you, you can meet this responsibility most easily simply by ensuring that all recursive bindings are lazy. You may instead choose to implement some light analysis to skip generating lazy bindings in some cases, such as if every initializer in the binding group is an
Abs
. You also may choose to reimplementapplyLazinessTransform
, or even develop a more sophisticated laziness transform for your backend. It is of course your responsibility to ensure that the result of whatever analysis you do is equivalent to the expected semantics.๐ New features:
- Implement the Reflectable type class (#4207 by @PureFunctor)
The
Reflectable
type class is a common interface for reflecting type-level values down to the term-level. Its instances are automatically solved by the compiler, and it allowsSymbol
,Int
,Boolean
, andOrdering
kinded types to be reflected to their term-level representations.- Implement native type-level integers (#4207 and #4267 by @PureFunctor and @JordanMartinez)
Added support for type-level integers and compiler-solved operations such as
Add
,Mul
,Compare
, andToString
. Type-level integers use theInt
type as their kind.- ๐จ Print compilation progress on the command line (#4258 by @PureFunctor)
This feature makes it so
purs compile
andpurs docs
now show compilation progress on the command line. Example output:[ 1 of 59] Compiling Type.Proxy [ 2 of 59] Compiling Type.Data.RowList ... [58 of 59] Compiling Effect.Class.Console [59 of 59] Compiling Test.Main
- โช Restore names of quantified variables during generalization (#4257 by @PureFunctor)
This makes the compiler aware of the names of quantified variables instantiated into unification variables, such that when the latter is generalized, semantic information is restored. For example:
addNumberSuffix :: forall a b c d. a -> b -> c -> d -> a addNumberSuffix a _ _ _ = a addNumberSuffix' = addNumberSuffix 0
Previously, inferring top-level declarations without type signatures would use
t
suffixed with an integer for type variables.forall t6 t7 t8. t6 -> t7 -> t8 -> Int
Now, the inferred type would refer back to their original names.
forall b6 c7 d8. b6 -> c7 -> d8 -> Int
- ๐ Support Glibc versions >=
2.24
(#4228 by @sd-yip)
Previously,
purs
required a Glibc version greater than or equal to2.27
. This requirement is relaxed to support a Glibc version down to2.24
.๐ Bugfixes:
- ๐ Fix warning suppression for wildcard types (#4269 by @rhendric)
This bug was triggered by defining recursive partial functions or recursive bindings that contained wildcards in inner type annotations. Recursive partial function declarations now no longer cause spurious wildcard warnings to be emitted, and actual user-written wildcards now accurately emit warnings if and only if they don't appear within a binding (recursive or otherwise) with a complete (wildcard-free) type signature.
- โ Remove compiler-generated identifiers from type search results (#4260 by @PureFunctor)
Other improvements:
- ๐ Improve "Unknown value bind" and "Unknown value discard" errors (#4272 by @mhmdanas)
The previous error implies that do-notation compiles down to only
bind
or to onlydiscard
(depending on whether the symbol not found wasbind
ordiscard
respectively), which is somewhat misleading, especially in the latter case. Now, the error states correctly that do-notation compiles down to both functions.Internal:
Document the
HSPEC_ACCEPT
flag for generating golden files (#4243 by @JordanMartinez)โ Fail test if PureScript file(s) don't have a
Main
module (#4243 by @JordanMartinez)โก๏ธ Update CI to use
windows-2019
sincewindows-2016
is deprecated (#4248 by @JordanMartinez)๐ Move
lib/purescript-cst
intosrc/
(#4290 by @JordanMartinez)โก๏ธ Update tests and their bower deps to 0.15.0-compatible versions (#4300 by @JordanMartinez)
-
v0.14.7 Changes
๐ New features:
๐ Make
Prim.TypeError
'sQuote
work on all kinds, not just kindType
. (#4142 by @xgrommx)๐ Display role annotations in HTML docs (#4121 by @JordanMartinez)
Previously, the HTML docs would not indicate which types could be safely coerced and which could not:
-- cannot be coerced data Foo1 a = Foo1 a type role Foo1 nominal -- can be coerced data Foo2 a = Foo2 type role Foo2 phantom -- can be coerced in some contexts data Foo3 a = Foo3 a type role Foo3 representational
The HTML docs now display the role annotations either explicitly declared by the developer or those inferred by the compiler.
Since role annotations are an advanced feature and since most type parameters' roles are the
representational
role, thephantom
andnominal
role annotations are displayed in documentation whereas therepresentational
role is not, similar to "uninteresting" kind signatures.Lastly, FFI declarations like below...
foreign import data Foo :: (Type -> Type) -> Type type role Foo nominal
...will be rendered as though they are data declarations:
data Foo :: (Type -> Type) -> Type data Foo t0 type role Foo nominal
One can distinguish FFI declarations with roles separately from normal
data
declarations that have roles based on the name of the type parameters. Since FFI declarations' type parameters are implicit and thus unnamed, the compiler will generate their name:t0
,t1
, ...,tN
whereN
is a zero-based index of the type parameter.Note: the resulting documentation will display the roles, but the roles will not be selectable when selecting the type in case one wants to copy-paste the type into source code.
- Rewrite
Partial
optimization to be cleaner (#4208 by @rhendric)
This feature shrinks the generated JS code for declarations that use empty type classes, such as
Partial
, but is otherwise not expected to have user-visible consequences.- โ Add support for publishing via the
purs.json
manifest format (#4233 by @thomashoneyman)
This feature expands compiler support for publishing packages with different manifest formats. Previously, packages had to have a
bower.json
manifest; now, packages can choose to have apurs.json
manifest instead.This feature provides only partial support for packages published to the PureScript registry using the
purs.json
manifest format. Registry packages are allowed to be hosted anywhere (not just GitHub), and do not need to be Git repositories at all. However,purs publish
and its primary consumer, Pursuit, both require packages to be available on GitHub and for their version to be a SemVer-compliant Git tag. Therefore, this feature only supports registry packages that are compatible with these restrictions.๐ Bugfixes:
โ Add missing source spans to data constructors when generating docs (#4202 by @PureFunctor)
Check role declarations arity during type checking (#4157 by @kl0tl)
โก๏ธ Optimize newtype applications with the ($) operator (#4205 by @PureFunctor)
Properly deserialize unused identifiers in the CoreFn (#4221 by @sjpgarcia)
This mostly affects downstream consumers of the CoreFn as discussed in #4201. This makes it so CoreFn deserialization properly reads
$__unused
intoUnusedIdent
instead of anIdent
. This is particularly useful for downstream consumers of the CoreFn such as alternative backends that don't allow arguments to be omitted from functions.- ๐ Fix type operators in declaration param kinds (#4220 by @rhendric)
This fixes an internal error triggered by using a type operator in the kind of a type parameter of a data declaration, type synonym declaration, or class declaration.
- Scope type vars when type checking typed values (#4216 by @rhendric)
When the compiler is checking an expression that is annotated with a type against another expected type, and the annotation introduces a type variable, the compiler needs to introduce that type variable to the scope of any types used inside the expression.
One noteworthy case of this pattern is member signatures inside instances. This fix allows type variables introduced in member signatures to be used in the member declaration itself.
Internal:
โฌ๏ธ Bump PureScript to building with GHC-8.10.7, as well as from LTS-17 to LTS-18. (#4199 by @cdepillabout)
Prevent hangs on internal errors (#4126 by @rhendric)
๐ The explicit disabling of Nix has been removed from
stack.yaml
. (#4198 by @cdepillabout)
For developers on NixOS, this means that you should be able to build PureScript by running
stack build
instead ofstack build --nix
. For other developers, this shouldn't affect you.- ๐ Build the entire latest package set in CI (#4217 by @rhendric)
See #4128.
- โ Create test machinery for optimizations (#4205 by @PureFunctor)
This adds machinery for testing code generation for optimizations.
Partially extracted from #3915 to add tests for #4205.
-
v0.14.6 Changes
๐ Do not use this release.
purescript-cst
's version wasn't bumped when this release was made. So, tools liketrypurescript
cannot depend on it. See 0.14.7 for the same thing. -
v0.14.5 Changes
๐ Bugfixes:
๐ Fix a case where kind inference inferred the wrong kind for type synonyms (#4184 by @jy14898)
Properly rename module imports in case of conflicts with declarations (#4188 by @PureFunctor)
Internal:
๐ Fix command and clarify a few other requirements in release guide (#4177 by @JordanMartinez)
โ Add
Functor
instance forLanguage.PureScript.CoreFn.Module
. (#4186 by @cdepillabout)
-
v0.14.4 Changes
๐ Bugfixes:
Solve
Prim.Row.Union left right all
constraint forleft
whenall
andright
are already closed rows, (#3720 by @MonoidMusician) reflecting the existing functional dependencyall right -> left
๐ Account for redundant parens when excluding uninteresting kind sigs from docs (#4137 by @JordanMartinez)
โ Add a hint for errors in foreign data type declarations (#4161 by @kl0tl)
๐ Do not remove bindings referenced in function declarations when bundling (#4044 by @kl0tl)
๐ Improve row type error messages (#4159 by @rhendric)
- Remove a redundant hint that repeats the types in the error
- Correctly diff rows containing duplicate items
- Erase kind applications from rows in errors (by default)
๐ Fix bad interaction between superclasses and type synonyms (#4164 by @rhendric)
See #4101.
๐ Fix regression in row unification (#4168 by @rhendric)
๐ Fix backtick operator rule (#4172 by @JordanMartinez)
Other improvements:
- โ Add developer guide to readme (#3900 by @milesfrain)
Internal:
- ๐ Move unreleased changelog entries to CHANGELOG.d (#4132 by @rhendric)
See CHANGELOG.d/README.md for details.
๐ Clarify in RELEASE_GUIDE what to do when broken releases are made (#4147 by @JordanMartinez)
๐ Miscellaneous updates/clarifications to the release guide (#4131 by @JordanMartinez)
๐ท Run Weeder in CI and make it happy (#4148 by @rhendric)
โ Add golden tests for self cycles in type class declarations, kind declarations and foreign data type declarations (#4162 by @kl0tl)
Represent class dictionaries as newtypes (#4125 by @rhendric)
-
v0.14.3 Changes
๐ New features:
- ๐ Display kind signatures and their comments in documentation (#4100 and #4119 by JordanMartinez)
The compiler now displays kind signatures for data, newtype, type synonym, and type class declarations in generated documentation. The compiler now also includes documentation-comments (i.e. those which start with a
|
character) both above and below the associated kind signature declaration (if any) in generated documentation, whereas previously documentation-comments above a kind signature declaration were ignored.Both explicitly declared and inferred kinds are included in documentation. The compiler omits including a kind signature in generated documentation only when the kind is considered "uninteresting". An uninteresting kind is defined as one where all of the declaration's type parameters have kind
Type
.๐ Bugfixes:
๐ Ensure unnamed instances appear in documentation (#4109 by @JordanMartinez)
๐ Allow fixity, kind, role declarations in REPL (#4046, @rhendric)
๐ท Pin OS versions used in CI (#4107, @f-f)
๐ Fix UnusedName warnings for multiple non-recursive let bindings (#4114 by @nwolverson)
โ Remove generated names from errors about instances (#4118 by @rhendric)
Internal:
๐ Fix for Haddock (#4072 by @ncaq and @JordanMartinez, #4139 by @JordanMartinez)
๐ Update RELEASE_GUIDE.md with more details (#4104 by @JordanMartinez)
๐ Use GenIdent for anonymous instances (#4096, @rhendric)
Desugar type class instance names in type class desugaring pass (#4099 by @JordanMartinez)
-
v0.14.2 Changes
๐ New features:
- ๐ Make type class instance names optional (#4085, @JordanMartinez)
Previously, one would be required to define a unique name for a type class instance. For example
-- instance naming convention: -- classNameType1Type2Type3 instance fooIntString :: Foo Int String
Now, the name and
::
separator characters are optional. The above instance could be rewritten like so:instance Foo Int String
and the compiler will generate a unique name for the instance (e.g.
$dollar_FooIntString_4
where4
is a randomly-generated number that can change across compiler runs). This version of the instance name is not intended for use in FFI.Note: if one wrote
instance ReallyLongClassName Int String
the generated name would be something like
$dollar_ReallyLongClassNameIntStr_87
rather than$dollar_ReallyLongClassNameIntString_87
as the generated part of the name will be truncated to 25 characters (long enough to be readable without being too verbose).๐ Bugfixes:
- โ Unused identifier warnings now report smaller and more relevant source spans (#4088, @nwolverson)
Also fix incorrect warnings in cases involving a let-pattern binding shadowing an existing identifier.
Internal:
- โฌ๏ธ Drop libtinfo dependency (#3696, @hdgarrood)
Changes the build configuration so that by default, compiler binaries will not have a dynamic library dependency on libncurses/libtinfo. This should alleviate one of the most common pains in getting the compiler successfully installed, especially on Linux. The cost is a slight degradation in the REPL experience when editing long lines, but this can be avoided by building the compiler with the libtinfo dependency by setting the
terminfo
flag of thehaskeline
library totrue
.๐ท Migrate CI from Travis to GitHub Actions (#4077, @rhendric)
โ Remove tasty from test suite and just use hspec (#4056, @hdgarrood)
โ Avoid compiling tests with diagnostics twice in test suite (#4079, @hdgarrood)
โ Do less work in test initialization (#4080, @rhendric)
๐ Follow more HLint suggestions (#4090, @rhendric)
Export
rebuildModule'
to speed up Try PureScript! slightly (#4095 by @JordanMartinez)๐ Merge
purescript-ast
intopurescript-cst
(#4094 by @JordanMartinez)
-
v0.14.1 Changes
๐ New features:
- ๐ Support TCO for functions with tail-recursive inner functions (#3958, @rhendric)
Adds support for optimizing functions that contain local functions which call the outer function in tail position, as long as those functions themselves are only called from tail position, either in the outer function or in other such functions.
This enables hand-written mutually-tail-recursive function groups to be optimized, but more critically, it also means that case guards which desugar to use local functions don't break TCO.
- โ Add warnings for unused names and values (#3819, @nwolverson)
The compiler now emits warnings when it encounters unused names in binders and unused value declarations. A declaration is considered to be unused if it is not exported and is also not reachable by any of the exported declarations. The compiler will not currently produce unused warnings about other kinds of declarations such as data and type class declarations, but we intend to produce warnings for these in the future as well.
๐ Bugfixes:
- ๐จ Make close punctuation printable in errors (#3982, @rhendric)
- Desugar type operators in top-level kind signatures (#4027, @natefaubion)
- ๐ Use type annotation hint only when needed (#4025, @rhendric)
๐ Fix pretty printing of "hiding" imports (#4058, @natefaubion)
Instantiate polymorphic kinds when unwrapping newtypes while solving Coercible constraints (#4040, @kl0tl)
๐ Fix row unification with shared unknown in tails (#4048, @rhendric)
๐ Fix kinded declaration reordering in desugaring (#4047, @rhendric)
๐ Fix wildly off kind unification positions (#4050, @natefaubion)
๐ Fix incorrect incremental builds with different
--codegen
options (#3911, #3914, @hdgarrood)
This bug meant that after invoking the compiler with different
--codegen
options, it was easy to end up with (for example) an outdated docs.json or corefn.json file in your output directory which would be incorrectly considered up-to-date by the compiler.Other improvements:
- โ Add white outline stroke to logo in README (#4003, @ptrfrncsmrph)
The previous
logo.png
was not legible against a dark background (#4001).๐ Show the constraints that were being solved when encountering a type error (@nwolverson, #4004)
โ Removed all shift/reduce conflicts in parser (#4063, @JordanMartinez).
Happy defaults to using "shift" rather than "reduce" in shift/reduce conflicts. This change merely makes explicit what is already happening implicitly.
Internal:
- โฌ๏ธ Upgrade tests Bower dependencies (#4041, @kl0tl)
- โ Remove unused Data.Foldable.foldr import (#4042, @kl0tl)