├── CONTRIBUTORS.md ├── README.md ├── Related-Projects.md ├── ecosystem ├── Alternate-backends.md ├── Editor-and-tool-support.md ├── Maintained-Packages.md ├── PureScript-Meetups.md └── PureScript-Presentations.md ├── errors ├── AdditionalProperty.md ├── AmbiguousTypeVariables.md ├── ArgListLengthsDiffer.md ├── CannotDerive.md ├── CannotDeriveNewtypeForData.md ├── CannotFindDerivingType.md ├── CannotGeneralizeRecursiveFunction.md ├── CannotGetFileInfo.md ├── CannotReadFile.md ├── CannotUseBindWithDo.md ├── CannotWriteFile.md ├── CaseBinderLengthDiffers.md ├── ClassInstanceArityMismatch.md ├── ConstrainedTypeUnified.md ├── CycleInDeclaration.md ├── CycleInModules.md ├── CycleInTypeSynonym.md ├── DeclConflict.md ├── DuplicateExportRef.md ├── DuplicateImport.md ├── DuplicateImportRef.md ├── DuplicateLabel.md ├── DuplicateModule.md ├── DuplicateSelectiveImport.md ├── DuplicateTypeArgument.md ├── DuplicateValueDeclaration.md ├── ErrorParsingFFIModule.md ├── ErrorParsingModule.md ├── EscapedSkolem.md ├── ExpectedType.md ├── ExpectedWildcard.md ├── ExportConflict.md ├── ExprDoesNotHaveType.md ├── ExtraneousClassMember.md ├── HidingImport.md ├── HoleInferredType.md ├── ImplicitImport.md ├── ImplicitQualifiedImport.md ├── ImportHidingModule.md ├── IncompleteExhaustivityCheck.md ├── IncorrectAnonymousArgument.md ├── IncorrectConstructorArity.md ├── InfiniteKind.md ├── InfiniteType.md ├── IntOutOfRange.md ├── InvalidDoBind.md ├── InvalidDoLet.md ├── InvalidFFIIdentifier.md ├── InvalidInstanceHead.md ├── InvalidNewtype.md ├── InvalidNewtypeInstance.md ├── InvalidOperatorInBinder.md ├── KindsDoNotUnify.md ├── MisleadingEmptyTypeImport.md ├── MissingClassMember.md ├── MissingFFIImplementations.md ├── MissingFFIModule.md ├── MissingTypeDeclaration.md ├── MixedAssociativityError.md ├── ModuleNotFound.md ├── MultipleFFIModules.md ├── MultipleTypeOpFixities.md ├── MultipleValueOpFixities.md ├── NameIsUndefined.md ├── NoInstanceFound.md ├── NonAssociativeError.md ├── OrphanInstance.md ├── OrphanTypeDeclaration.md ├── OverlappingArgNames.md ├── OverlappingInstances.md ├── OverlappingNamesInLet.md ├── OverlappingPattern.md ├── PartiallyAppliedSynonym.md ├── PossiblyInfiniteInstance.md ├── PropertyIsMissing.md ├── RedefinedIdent.md ├── ScopeConflict.md ├── ScopeShadowing.md ├── ShadowedName.md ├── ShadowedTypeVar.md ├── Template.md ├── TransitiveDctorExportError.md ├── TransitiveExportError.md ├── TypeSynonymInstance.md ├── TypesDoNotUnify.md ├── UndefinedTypeVariable.md ├── UnknownClass.md ├── UnknownExport.md ├── UnknownExportDataConstructor.md ├── UnknownImport.md ├── UnknownImportDataConstructor.md ├── UnknownName.md ├── UnnecessaryFFIModule.md ├── UnusedDctorExplicitImport.md ├── UnusedDctorImport.md ├── UnusedExplicitImport.md ├── UnusedFFIImplementations.md ├── UnusedImport.md ├── UnusedTypeVar.md ├── UserDefinedWarning.md └── WildcardInferredType.md ├── guides ├── Common-Operators.md ├── Contrib-Guidelines.md ├── Custom-Type-Errors.md ├── Error-Suggestions.md ├── FFI-Tips.md ├── FFI.md ├── Getting-Started.md ├── PSCi.md ├── PureScript-Without-Node.md ├── Style-Guide.md ├── The-Partial-type-class.md └── psc-ide-FAQ.md ├── historical ├── 0.10-Migration-Guide.md └── Pre-0.5-changelog.md └── language ├── Differences-from-Haskell.md ├── FFI.md ├── Modules.md ├── Pattern-Matching.md ├── README.md ├── Records.md ├── Syntax.md ├── Type-Classes.md └── Types.md /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | 3 | This file lists the contributors to the PureScript documentation project, and the terms under which their contributions are licensed. 4 | 5 | **NOTICE:** This list is not yet exhaustive, and any content written by contributors not listed here is not yet explicitly licensed. 6 | 7 | ### Contributors using Standard Terms 8 | 9 | Contributors listed here agree to license their contributions under the following terms: 10 | 11 | > My existing contributions and all future contributions until further notice are Copyright {Name}, and are licensed to the owners and users of the PureScript documentation project under the terms of the {License}. 12 | 13 | By adding your name to the list below, you agree to license your contributions under these following terms. 14 | 15 | If you would prefer to use different terms, please use the section below instead. 16 | 17 | | Username | Name | License | 18 | | :------- | :--- | :------ | 19 | | [@LiamGoodacre](https://github.com/LiamGoodacre) | Liam Goodacre | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 20 | | [@hdgarrood](https://github.com/hdgarrood) | Harry Garrood | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 21 | | [@jplatte](https://github.com/jplatte) | Jonas Platte | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 22 | | [@garyb](https://github.com/garyb) | Gary Burgess | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 23 | | [@nwolverson](https://github.com/nwolverson) | Nicholas Wolverson | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 24 | | [@csicar](https://github.com/csicar) | Carsten Csiky | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 25 | | [@andyarvanitis](https://github.com/andyarvanitis) | Andy Arvanitis | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 26 | | [@jdegoes](https://github.com/jdegoes) | John A. De Goes | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 27 | | [@epost](https://github.com/epost) | Erik Post | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 28 | | [@paf31](https://github.com/paf31) | Phil Freeman | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 29 | | [@kRITZCREEK](https://github.com/kRITZCREEK) | Christoph Hegemann | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 30 | | [@stefanholzmueller](https://github.com/stefanholzmueller) | Stefan Holzmüller | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 31 | | [@damncabbage](https://github.com/damncabbage) | Rob Howard | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 32 | | [@dgendill](https://github.com/dgendill) | Dominick Gendill | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 33 | | [@haf](https://github.com/haf) | Henrik Feldt | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 34 | | [@Xandaros](https://github.com/Xandaros) | @Xandaros | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 35 | | [@kika](https://github.com/kika) | Kirill Pertsev | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 36 | | [@chexxor](https://github.com/chexxor) | Alex Berg | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 37 | | [@mattaudesse](https://github.com/mattaudesse) | Matt Audesse | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 38 | | [@juhp](https://github.com/juhp) | Jens Petersen | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 39 | | [@gabejohnson](https://github.com/gabejohnson) | Gabe Johnson | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 40 | | [@Profpatsch](https://github.com/Profpatsch) | Profpatsch | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 41 | | [@carstenkoenig](https://github.com/carstenkoenig) | Carsten König | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 42 | | [@anttih](https://github.com/anttih) | Antti Holvikari | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 43 | | [@Jyothsnasrinivas](https://github.com/Jyothsnasrinivas) | Jyothsna Patnam | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 44 | | [@MiyamotoAkira](https://github.com/MiyamotoAkira) | Jorge Gueorguiev Garcia | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 45 | | [@justinwoo](https://github.com/justinwoo) | Justin Woo | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 46 | | [@hrb90](https://github.com/hrb90) | Harrison Brown | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 47 | | [@rmies](https://github.com/rmies) | Michel Rijnders | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 48 | | [@jordanmartinez](https://github.com/jordanmartinez) | Jordan Martinez | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 49 | | [@mseri](https://github.com/mseri) | Marcello Seri | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 50 | | [@narrative](https://github.com/narrative) | Erik Stevenson | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 51 | | [@shuhei](https://github.com/shuhei) | Shuhei Kagawa | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 52 | | [@owickstrom](https://github.com/owickstrom) | Oskar Wickström | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 53 | | [@soupi](https://github.com/soupi) | Gil Mizrahi | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 54 | | [@FungusHumungus](https://github.com/FungusHumungus) | Stephen Wakely | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 55 | | [@Beyarz](https://github.com/Beyarz) | Beyar N | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 56 | | [@toraritte](https://github.com/toraritte) | Attila Gulyas | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 57 | | [@bernhard-herzog](https://github.com/bernhard-herzog) | Bernhard Herzog | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed) | 58 | 59 | ### Contributors using Modified Terms 60 | 61 | | Username | Name | Terms | 62 | | :------- | :--- | :------ | 63 | 64 | ### Companies 65 | 66 | | Username | Company | Terms | 67 | | :------- | :--- | :------ | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![PureScript](https://github.com/purescript/purescript/raw/master/logo.png) 2 | 3 | 6 | PureScriptのドキュメントリポジトリへようこそ! 7 | 8 | 12 | PureScriptは、小さくて、JavaScriptへコンパイルされる強い型付け言語です。 13 | PureScriptの概要をもっと見たいなら、[The PureScript Website](http://purescript.org)にアクセスしてください。 14 | 15 | 18 | このリポジトリはみんなの努力の結晶ですから、編集や追加、プルリクエストをしたり、議論を重ねることを厭わず、気軽に行ってください。PureScriptは様々なバックグラウンドを持つ人々に利用される巨大なプロジェクトです。多様な人々にとって便利なドキュメントを作ることは本当に難しいため、内容の不足を指摘してくれるあなたのような読者を必要としています。よろしくお願いします! 19 | 20 | 23 | ## リンク集 24 | 25 | 28 | ### 入門 29 | 30 | 35 | - [Getting Started](guides/Getting-Started.md): PureScriptのダウンロードから初めてのプロジェクトをビルドする方法までを解説しています。 36 | - [PureScript By Example](https://leanpub.com/purescript/read): PureScriptについての本です。実用的な問題解決法をWebに役立てる関数型プログラミングの手法を学びます。 37 | - [Try PureScript](http://try.purescript.org): PureScriptをWebブラウザから試すことができます。 38 | 39 | 42 | ### 学習 43 | 44 | 53 | - [PureScript Book](https://leanpub.com/purescript/read) は、PureScriptに関するより多くのことを深く学習するためにおすすめの手段ですが、対応するコンパイラのバージョンが`0.11.7`のままで、`0.12.x`には未対応です。そのため、以下の記事の内容も合わせて知っておくべきです。 54 | - [dwhitney's fork of the book's exercises](https://github.com/dwhitney/purescript-book) `0.12.x`に対応しています。 55 | - [Justin's `0.11.7` to `0.12.x` summary](https://purescript-resources.readthedocs.io/en/latest/0.11.7-to-0.12.0.html) 古くなった本に含まれるソースコードを正しく動くように「翻訳」する方法を知ることができます。 56 | - [deprecated packages](https://github.com/purescript-deprecated) ここに含まれる内容には常に注意を払ってください(廃止予定のモジュール集)。 57 | - [Language Reference](language/README.md) 58 | - [PureScript: Jordan's Reference](https://github.com/JordanMartinez/purescript-jordans-reference): 入門、ビルドツール、PureScriptの構文の例、関数型プログラミングのデザインパターン、PureScriptのエコシステムなどをカバーする最新のプロジェクト集です。 59 | - [A guide to the PureScript numeric hierarchy](https://a-guide-to-the-purescript-numeric-hierarchy.readthedocs.io/en/latest/index.html): PureScriptのPreludeに含まれる型クラスの数値の階層に隠れた数学についての解説です。[PureScript numeric hierarchy overview](https://harry.garrood.me/numeric-hierarchy-overview/)も参照してください。 60 | 61 | 64 | ### ガイド集 65 | 66 | 77 | - [演算子](guides/Common-Operators.md) 78 | - [外部関数インタフェース(FFI)](guides/FFI.md) 79 | - [外部関数インタフェース Tips集](guides/FFI-Tips.md) 80 | - [Custom Type Errors](guides/Custom-Type-Errors.md) 81 | - [Nodeを使わないPureScript](guides/PureScript-Without-Node.md) 82 | - [準標準ライブラリ(Contrib Library)のガイドライン](guides/Contrib-Guidelines.md) 83 | - [エラー・警告を指摘するツール](guides/Error-Suggestions.md) 84 | - [psc-ideについてのよくある質問集](guides/psc-ide-FAQ.md) 85 | - [Try PureScriptについて](https://github.com/purescript/trypurescript/blob/gh-pages/README.md) 86 | 87 | 90 | ### ツール 91 | 92 | 97 | - [エディタとツール](ecosystem/Editor-and-tool-support.md): エディタプラグインとビルドツール、その他開発ツールについてのリンク集です。 98 | - [PureScript and NixOS](https://pr06lefs.wordpress.com/2015/01/11/get-started-with-purescript-on-nixos/): NixOS上でPureScriptを使う方法の解説です。 99 | - [PSCi](guides/PSCi.md): PureScriptの対話式開発ツールについての解説です。 100 | 101 | 104 | ### エコシステム 105 | 106 | 111 | - [メンテナンスされたパッケージ](ecosystem/Maintained-Packages.md) 112 | - [スタイルガイド](guides/Style-Guide.md) 113 | - [別のコンパイルターゲット](https://github.com/purescript/documentation/blob/master/ecosystem/Alternate-backends.md): PureScriptを別の言語にコンパイルすることが可能です! 114 | 115 | 118 | ### 記事集 119 | 120 | - [24 Days of PureScript 2016](https://github.com/paf31/24-days-of-purescript-2016) 121 | 122 | 125 | ### トーク・会合 126 | 127 | - [PureScriptプレゼン](ecosystem/PureScript-Presentations.md) 128 | - [PureScript会合](ecosystem/PureScript-Meetups.md) 129 | 130 | 133 | ### 関連のある言語 134 | 135 | 139 | - [関連するプロジェクト](Related-Projects.md) 140 | - [Haskellとの違い](language/Differences-from-Haskell.md) 141 | 142 | 143 | 146 | ## プロジェクトの範囲 147 | 148 | 151 | 現在、このプロジェクトは以下のトピックを扱っています: 152 | 153 | 160 | - PureScriptの言語リファレンス・ドキュメント 161 | - コンパイラのエラー 162 | - PureScriptの基盤となるコアコンセプト 163 | - 似た言語との比較 164 | - 別の提供元にあるドキュメントの紹介 165 | 166 | 169 | 現在、このプロジェクトは以下のトピックを**扱っていません**: 170 | 171 | 176 | - PureScriptライブラリの使用 (これらは各ライブラリに付属しています) 177 | - PureScriptの学習コース ([PureScript by Example](https://leanpub.com/purescript/read)やその他の記事を参照してください) 178 | - パッケージマネージャと依存関係の管理についての紹介 179 | 180 | 183 | どうぞ気軽に、issueを立てたり、プロジェクト範囲の見直しについて話し合ってください。 184 | -------------------------------------------------------------------------------- /Related-Projects.md: -------------------------------------------------------------------------------- 1 | # Related Projects 2 | 3 | PureScript might be compared to other AltJS projects such as Roy, Haste, Fay, Elm and GHCJS. Certainly, there is a lot of overlap in terms of syntax, but the goals of PureScript listed above separate it in one or more ways from each of these languages. 4 | 5 | ## Roy 6 | 7 | Roy is probably the most similar language on the list, and was a large influence on the development of PureScript. There are however, key differences in the foreign function interface, the type system and the choice of development language (Haskell vs. Javascript) 8 | 9 | ## Haste, Fay, GHCJS 10 | 11 | Projects such as Haste, Fay and GHCJS aim to compile Haskell (or a subset) to Javascript, while preserving Haskell's semantics. 12 | 13 | This approach gives the advantage that tools and libraries can be shared with Haskell, but often at the cost of the size of the generated Javascript. This is the main practical difference between PureScript and these projects. 14 | 15 | PureScript takes inspiration from Haskell in terms of its syntax and type system, but does not try to model its semantics. In this sense, PureScript can be thought of as simply an environment in which to write principled Javascript. 16 | 17 | ## Elm 18 | 19 | Elm also shares a lot in terms of functionality with PureScript. Elm is designed for functional reactive programming, and focusses on tools and language features suitable for that domain, while PureScript focusses on the development of purely functional core application logic. Another difference between PureScript and Elm is PureScript’s lack of a runtime system. 20 | -------------------------------------------------------------------------------- /ecosystem/Alternate-backends.md: -------------------------------------------------------------------------------- 1 | 4 | `psc`のデフォルトのJavaScriptには様々な代替バックエンドが存在します: 5 | 6 | 9 | ## 活発にメンテナンスされているもの 10 | 11 | | source code | PS version | Target | status | comments | 12 | |:--------------------------------------------------------------------------------------|:-----------|:--------------|:------|:-----------------------| 13 | | [andyarvanitis/purescript-native](https://github.com/andyarvanitis/purescript-native) | 0.13.x | C++11 | active | `./examples/passing`の全テストは通っています | 14 | | [purerl/purescript](https://github.com/purerl/purescript) | 0.12.0 | Erlang | active | 15 | 16 | 19 | ## アルファ版 20 | 21 | | source code | PS version | Target | 22 | |:----------------------------------------------------------------------------------------|:-----------|:--------------| 23 | | [andyarvanitis/purescript-clojure](https://github.com/andyarvanitis/purescript-clojure) | | Clojure (JVM) | 24 | | [pure-c/pure-c](https://github.com/pure-c/pure-c) | | C (Clang) | 25 | | [epost/psc-query](https://github.com/epost/psc-query) | 0.11.7 | Datalog | 26 | | [tfausak/thran](https://github.com/tfausak/thran) | 0.11.6 | Haskell (GHC) | 27 | 28 | 31 | ## 古いもの 32 | 33 | | source code | PS version | Target | 34 | |:--------------------------------------------------------------------------------------|:-----------|:--------------| 35 | | [lua-purescript/purescript](https://github.com/lua-purescript/purescript) | 0.9.1.0 | Lua | 36 | | [slamdata/truffled-purescript](https://github.com/slamdata/truffled-purescript) | 0.7.5.x | Truffle (JVM) | 37 | | [osa1/psc-lua](https://github.com/osa1/psc-lua) | 0.5.x | Lua | 38 | | [Gabriel439/Purescript-to-Python](https://github.com/Gabriel439/Purescript-to-Python) | | Python | 39 | | [PyreScript](https://github.com/joneshf/pyrescript) | 0.9.1 | Python | 40 | -------------------------------------------------------------------------------- /ecosystem/Editor-and-tool-support.md: -------------------------------------------------------------------------------- 1 | 4 | ## エディタ 5 | 6 | #### Atom 7 | 8 | 12 | - [purescript-contrib/atom-language-purescript](https://github.com/purescript-contrib/atom-language-purescript) 構文ハイライトを提供します 13 | - [nwolverson/atom-ide-purescript](https://github.com/nwolverson/atom-ide-purescript) ビルド支援、REPL、自動補完を[psc-ide](https://github.com/purescript/purescript/tree/master/psc-ide)を通じて提供します 14 | 15 | #### Emacs 16 | 17 | 22 | 次の2つのパッケージをインストールし、`psc-ide-emacs`のREADMEに従ってください。 23 | - [purescript-mode](https://github.com/purescript-emacs/purescript-mode) 構文ハイライトとインデント (haskell-modeから採用されました) 24 | - [psc-ide-emacs](https://github.com/purescript-emacs/psc-ide-emacs) コンパイラのIDE支援を公開しているEmacsプラグインです 25 | 26 | 29 | もしくは、更に小さい設定のためには次の2つを使います: 30 | 31 | 35 | - [emacs-pe/purescript-mode](https://github.com/emacs-pe/purescript-mode) alpha-stageのグリーンフィールドモードです 36 | - [emacs-pe/flycheck-purescript](https://github.com/emacs-pe/flycheck-purescript) flycheckをサポートしています 37 | 38 | 39 | 42 | comintを通じてPSCIをサポートするもの: 43 | 44 | 47 | - [psci-mode](https://github.com/purescript-emacs/emacs-psci) REPLのマイナーモードです 48 | 49 | 50 | 53 | Spacemacsユーザは[`purescript`層](https://github.com/syl20bnr/spacemacs/tree/master/layers/%2Blang/purescript)を使えます。 54 | 55 | #### Sublime Text 2 56 | 57 | 60 | - [PureScriptパッケージ](https://sublime.wbond.net/search/PureScript) 作者:joneshf 61 | 62 | #### Vim 63 | 64 | 67 | - [purescript-vim](https://github.com/raichoo/purescript-vim) 構文ハイライトと字下げ 68 | - [FrigoEU/psc-ide-vim](https://github.com/FrigoEU/psc-ide-vim/) 69 | - [w0rp/ale](https://github.com/w0rp/ale) supports the [purescript-language-server](https://github.com/nwolverson/purescript-language-server) 70 | 71 | #### VS Code 72 | 73 | - [nwolverson/vscode-ide-purescript](https://github.com/nwolverson/vscode-ide-purescript) 74 | 75 | 78 | #### 全般 79 | 80 | 83 | - `purs docs --format etags`(または`--format ctags`)を使用して`TAGS`ファイルを生成できます。 84 | 85 | 88 | ## ビルドツールとパッケージマネージャ 89 | 90 | 101 | - [Pulp](https://github.com/purescript-contrib/pulp) - PureScript (`npm`の[pulp](https://www.npmjs.com/package/pulp))用のスタンドアロン型ビルドシステム 102 | - [psc-package](https://github.com/purescript/psc-package): - package setsの概念を基にしたPureScriptパッケージマネージャ 103 | - [Gulp task](https://github.com/purescript-contrib/gulp-purescript) (`npm`の`gulp-purescript`) 104 | - [psvm-js](https://github.com/ThomasCrvsr/psvm-js) - PureScriptバージョンマネージャ 105 | - [purs-loader](https://github.com/ethul/purs-loader/) - WebPack用のPureScriptローダ 106 | - [psc-pane](https://github.com/anttih/psc-pane) - ウインドウに合うように1つのエラーを整形する自動リロードコンパイラ 107 | - [purescript-psa](https://github.com/natefaubion/purescript-psa) - 色付き、元のエラー範囲、警告のフィルタリング、永続性を特徴とする、`psc`のための可愛く柔軟な、エラー/警告を報告するフロントエンド 108 | - [pscid](https://github.com/kRITZCREEK/pscid) エディタに依存せずinstant-rebuildを提供する、PureScriptプロジェクト用の軽量ファイルウォッチャー/テストランナー -------------------------------------------------------------------------------- /ecosystem/Maintained-Packages.md: -------------------------------------------------------------------------------- 1 | 4 | # メンテナンスされているPureScriptパッケージ 5 | 6 | 9 | 以下のリソースではPureScriptコミュニティによって書かれ、活発にメンテナンスされているライブラリを発見することができます。 10 | 11 | 15 | - [Pursuit](https://pursuit.purescript.org)は、ライブラリのドキュメントを提供するPureScriptのパッケージデータベースです。Pursuit上のパッケージは最新のメジャーリリースのコンパイラと互換性を持たなければならず、これによってパッケージがうまくメンテナンスされるようになっています。 16 | - [package set](https://github.com/purescript/package-sets)リポジトリは、様々なバージョンのPureScriptコンパイラでビルドされている精選されたパッケージのリストです。このリストはPursuitほど完全ではありませんが、特定のコンパイラバージョンに固有のもので、各コンパイラリリースに1パッケージがタグ付けされています。 17 | -------------------------------------------------------------------------------- /ecosystem/PureScript-Meetups.md: -------------------------------------------------------------------------------- 1 | 4 | # PureScriptコミュニティ会合 5 | 6 | 10 | * [PureScript Unscripted](#purescript-unscripted) 11 | * [Web会議室のリンク](#Web会議室) 12 | 13 | 16 | 今後の会合の情報と出席については、[gathering.purescript.org](https://gathering.purescript.org)を参照してください。 17 | 18 | *** 19 | 20 | ## PureScript Unscripted 21 | 22 | 25 | 私たちはコミュニティ内のプロジェクトや概念を学ぶために月1回のビデオ会議をしています!現在は参加者を50人に制限していますが、その後[YouTubeチャンネル](https://www.youtube.com/channel/UCPtHLGu_WXh-OvX8NAVtDEw)に投稿しています。ピザを用意して見ましょう;) 26 | 27 | 30 | 発表者に答えてほしい質問があれば書いてください。 31 | 32 | [Youtube上のPureScriptコミュニティプレイリスト](https://www.youtube.com/playlist?list=PLQDWDZypikvGSNomRZNzBF2ARFLgW4TOV) 33 | 34 | 37 | 何を勉強したいですか?発表したいですか?[私たちにメールを送る](mailto:purescript.community@gmail.com)か、Twitterで@alex_bergへDMを送ってください!その他の話題に関する投票は[AllOurIdeas.org/purescript-unscripted-topics](http://www.allourideas.org/purescript-unscripted-topics/)を参照してください。 38 | 39 | 42 | ### スケジュール 43 | 44 | 47 | 月の第二土曜日の午後1時(太平洋標準時) 48 | 49 | 53 | - [WorldTimeBuddy TimeConverter](http://www.worldtimebuddy.com/?qm=1&lid=5391959,2643743,658225,2147714&h=5391959&date=2016-4-23&sln=13-15) 54 | - [Google カレンダー: PureScript Unscripted](https://calendar.google.com/calendar/embed?src=Ym03N2g1cmlhYW8wc2s2anBlczBrOGx2NGtAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ) 55 | 56 | 59 | ### Web会議室 60 | 61 | 64 | PureScriptコミュニティのZoom Roomです(以下を見てください) 65 | 66 | *** 67 | 68 | 69 | 72 | ## Web会議室のリンク 73 | 74 | 77 | ### PureScriptコミュニティのZoom Room 78 | 79 | 82 | 現在はAlex Bergが所有しているため、彼に開始と管理を頼む必要があります(バックアップが必要です)。 83 | 84 | 87 | PC、Mac、Linux、iOS、またはAndroidから参加してください:https://zoom.us/j/118616185 88 | 89 | 96 | またはiPhone one-tap (US通話料): +16465588656,118616185# or +14086380968,118616185# 97 | または電話: 98 | 電話番号: +1 646 558 8656 (US通話料) or +1 408 638 0968 (US通話料) 99 | Meeting ID: 118 616 185 100 | 有効な国際メンバー: https://zoom.us/zoomconference?m=w4bACzc4b_ocxEMimJTL9bn04r0jrDVv 101 | -------------------------------------------------------------------------------- /ecosystem/PureScript-Presentations.md: -------------------------------------------------------------------------------- 1 | 4 | PureScriptの話題に関する有用なプレゼンを気軽に追加してください。Twitterで[@alex_berg](https://twitter.com/alex_berg)に連絡するか、ここにリンクを追加してください。 5 | 6 | 9 | ## 会議 10 | 11 | 14 | [PureScriptコミュニティのプレイリスト: 会議](https://www.youtube.com/playlist?list=PLQDWDZypikvEyz4Eu08BEM8feZPWlss06) 15 | 16 | 19 | ## リモート会合 20 | 21 | [PureScriptコミュニティのプレイリスト: リモート会合](https://www.youtube.com/playlist?list=PLQDWDZypikvGSNomRZNzBF2ARFLgW4TOV) 22 | 23 | ## ローカル会合 24 | 25 | [PureScriptコミュニティのプレイリスト: ローカル会合](https://www.youtube.com/playlist?list=PLQDWDZypikvFWBZfxgjz_PUUhL4q_UeWa) 26 | 27 | ## コーディング 28 | 29 | [PureScriptコミュニティのプレイリスト: コーディング](https://www.youtube.com/playlist?list=PLQDWDZypikvFOZD4tdGqbSfe3xVIL1zhK) 30 | -------------------------------------------------------------------------------- /errors/AdditionalProperty.md: -------------------------------------------------------------------------------- 1 | # `AdditionalProperty` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/AmbiguousTypeVariables.md: -------------------------------------------------------------------------------- 1 | # `AmbiguousTypeVariables` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ArgListLengthsDiffer.md: -------------------------------------------------------------------------------- 1 | # `ArgListLengthsDiffer` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotDerive.md: -------------------------------------------------------------------------------- 1 | # `CannotDerive` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | data Bool = True | False 7 | 8 | derive instance showBool :: Show Bool 9 | ``` 10 | 11 | ## Cause 12 | 13 | This error shows up when you're attempting to derive an instance for a class 14 | for which compiler support does not exist. There is a [fixed list of classes 15 | which can be derived by the compiler][derivable]; for any class not on this 16 | list, however, you'll need to find another way of obtaining an instance. 17 | 18 | ## Fix 19 | 20 | - You will need to write an instance yourself. 21 | - For many classes (including `Show`), you can use [Generics][] to obtain the 22 | instances you want with less effort. 23 | 24 | [Generics]: https://pursuit.purescript.org/packages/purescript-generics-rep 25 | [derivable]: https://github.com/purescript/documentation/blob/master/language/Type-Classes.md#type-class-deriving 26 | -------------------------------------------------------------------------------- /errors/CannotDeriveNewtypeForData.md: -------------------------------------------------------------------------------- 1 | # `CannotDeriveNewtypeForData` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotFindDerivingType.md: -------------------------------------------------------------------------------- 1 | # `CannotFindDerivingType` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotGeneralizeRecursiveFunction.md: -------------------------------------------------------------------------------- 1 | # `CannotGeneralizeRecursiveFunction` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotGetFileInfo.md: -------------------------------------------------------------------------------- 1 | # `CannotGetFileInfo` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotReadFile.md: -------------------------------------------------------------------------------- 1 | # `CannotReadFile` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotUseBindWithDo.md: -------------------------------------------------------------------------------- 1 | # `CannotUseBindWithDo` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CannotWriteFile.md: -------------------------------------------------------------------------------- 1 | # `CannotWriteFile` Error 2 | 3 | ## Example 4 | 5 | ```text 6 | $ pulp build 7 | 8 | Compiling Main 9 | Error found: 10 | 11 | Unable to write file: 12 | 13 | output/Main/index.js 14 | 15 | See https://github.com/purescript/purescript/wiki/Error-Code-CannotWriteFile for more information, 16 | or to contribute content related to this error. 17 | ``` 18 | 19 | ## Cause 20 | 21 | The `CannotWriteFile` error is thrown when `psc`, `psci` or `psc-ide-server` cannot write to the filesystem. `psc` writes to various files, but this usually occurs when trying to write out compiled JavaScript files. 22 | 23 | ## Fix 24 | 25 | - Make sure the target directory (usually `output`) exists and is writable. 26 | - If you are using `psc-ide-server` then try restarting the process before retrying. 27 | - Try deleting the `output` directory and building again. If you are using `psci`, then you might like to try deleting the `.psci_modules` directory. 28 | 29 | ## Notes 30 | -------------------------------------------------------------------------------- /errors/CaseBinderLengthDiffers.md: -------------------------------------------------------------------------------- 1 | # `CaseBinderLengthDiffers` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ClassInstanceArityMismatch.md: -------------------------------------------------------------------------------- 1 | # `ClassInstanceArityMismatch` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ConstrainedTypeUnified.md: -------------------------------------------------------------------------------- 1 | # `ConstrainedTypeUnified` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/CycleInDeclaration.md: -------------------------------------------------------------------------------- 1 | # `CycleInDeclaration` Error 2 | 3 | ## Example 4 | 5 | ```text 6 | $ pulp repl 7 | 8 | > x = x 9 | Error found: 10 | at line 1, column 5 - line 1, column 9 11 | 12 | The value of x is undefined here, so this reference is not allowed. 13 | 14 | 15 | See https://github.com/purescript/documentation/blob/master/errors/CycleInDeclaration.md for more information, 16 | or to contribute content related to this error. 17 | ``` 18 | 19 | ## Cause 20 | 21 | This error occurs when a value refers to itself, or another value in the same binding group, at a point where such a reference would be unavailable because of _strict evaluation_. 22 | 23 | In the example above, it would be incorrect to generate the JavaScript 24 | 25 | ```javascript 26 | var x = x; 27 | ``` 28 | 29 | since then `x` would be `undefined`. 30 | 31 | Note that cycles can also spring up in much less obvious ways, e.g. if you define one typeclass member using another. 32 | 33 | ## Fix 34 | 35 | - Consider the problem again, keeping PureScript's strict evaluation in mind. How would you solve this problem in JavaScript, for example? 36 | - Sometimes you can break the cycle by strategically using eta expansion (`\x -> f x` instead of `f`) or using do-notation, which will introduce a function to the same effect because of `bind`. 37 | - You might be able to make use of the `Control.Lazy` module, and the [`fix`](https://pursuit.purescript.org/packages/purescript-control/4.1.0/docs/Control.Lazy#v:fix) function in particular. 38 | 39 | ## Notes 40 | 41 | - If you are trying to implement a recursive parser in PureScript, then you might find this post on [recursive parsing in PureScript](https://github.com/Thimoteus/SandScript/wiki/2.-Parsing-recursively) to be helpful. 42 | -------------------------------------------------------------------------------- /errors/CycleInModules.md: -------------------------------------------------------------------------------- 1 | # `CycleInModules` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Foo where 7 | 8 | import Bar 9 | ``` 10 | 11 | ```purescript 12 | module Bar where 13 | 14 | import Foo 15 | ``` 16 | 17 | ## Cause 18 | 19 | This problem occurs when two modules depend on each other. 20 | 21 | For example, given the `Foo` and `Bar` modules above, the compiler will fail with: 22 | 23 | ``` 24 | Error found: 25 | There is a cycle in module dependencies in these modules: 26 | 27 | Foo 28 | Bar 29 | 30 | See https://github.com/purescript/purescript/wiki/Error-Code-CycleInModules for more information, 31 | or to contribute content related to this error. 32 | ``` 33 | 34 | ## Fix 35 | 36 | - Break modules into smaller parts, in order to break the cycle of dependencies. 37 | - Alternatively, it might be possible to combine the two modules into a single module. 38 | 39 | ## Notes 40 | -------------------------------------------------------------------------------- /errors/CycleInTypeSynonym.md: -------------------------------------------------------------------------------- 1 | # `CycleInTypeSynonym` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DeclConflict.md: -------------------------------------------------------------------------------- 1 | # `DeclConflict` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DuplicateExportRef.md: -------------------------------------------------------------------------------- 1 | # `DuplicateExportRef` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DuplicateImport.md: -------------------------------------------------------------------------------- 1 | # `DuplicateImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Data.Maybe 9 | import Data.Maybe 10 | 11 | test = Nothing 12 | ``` 13 | 14 | ## Cause 15 | 16 | The same module has been imported multiple times (with the same qualification if any). 17 | 18 | ## Fix 19 | 20 | Remove one of the extra import statements. 21 | 22 | ## Notes 23 | 24 | [This error is auto-fixable](../guides/Error-Suggestions.md). 25 | -------------------------------------------------------------------------------- /errors/DuplicateImportRef.md: -------------------------------------------------------------------------------- 1 | # `DuplicateImportRef` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Prelude (unit, unit) 9 | 10 | test = unit 11 | ``` 12 | 13 | ## Cause 14 | 15 | An explicit import list contains multiple references to the same thing, i.e. has duplicates. 16 | 17 | ## Fix 18 | 19 | Remove the extraneous items. 20 | 21 | ## Notes 22 | -------------------------------------------------------------------------------- /errors/DuplicateLabel.md: -------------------------------------------------------------------------------- 1 | # `DuplicateLabel` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DuplicateModule.md: -------------------------------------------------------------------------------- 1 | # `DuplicateModule` Error 2 | 3 | ## Cause 4 | 5 | This error occurs when two modules have the same name. 6 | 7 | ## Fix 8 | 9 | - Make sure your module names are correct. 10 | - Check to make sure you do not have any duplicate modules in your dependencies. 11 | - If you are passing input files to the compiler using a wildcard, make sure it is not 12 | including any files twice. 13 | 14 | ## Notes 15 | -------------------------------------------------------------------------------- /errors/DuplicateSelectiveImport.md: -------------------------------------------------------------------------------- 1 | # `DuplicateSelectiveImport` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DuplicateTypeArgument.md: -------------------------------------------------------------------------------- 1 | # `DuplicateTypeArgument` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/DuplicateValueDeclaration.md: -------------------------------------------------------------------------------- 1 | # `DuplicateValueDeclaration` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ErrorParsingFFIModule.md: -------------------------------------------------------------------------------- 1 | # `ErrorParsingFFIModule` Error 2 | 3 | ## Cause 4 | 5 | This error occurs when the compiler cannot verify foreign declarations in JavaScript code, 6 | because it was unable to parse a JavaScript file. 7 | 8 | ## Fix 9 | 10 | - Verify the JavaScript code in your foreign modules. 11 | - Foreign modules should conform to the ES5 specification. Values in foreign modules should be provided in the form `exports.name = value;`. 12 | 13 | ## Notes 14 | 15 | - This [article](../guides/FFI.md) explains how to create foreign modules. 16 | - An example can be found [here](https://github.com/purescript/purescript-eff/blob/v1.0.0/src/Control/Monad/Eff.js). 17 | -------------------------------------------------------------------------------- /errors/ErrorParsingModule.md: -------------------------------------------------------------------------------- 1 | # `ErrorParsingModule` Error 2 | 3 | ## Cause 4 | 5 | This error occurs when the compiler is unable to parse a source file. 6 | 7 | ## Fix 8 | 9 | - Look carefully at the parse error and try to find the mistake in the source code. 10 | In particular, look at the source range and the list of expected tokens. 11 | - If the compiler complains about indentation, then it will include information about the 12 | expected column number, which can be useful for tracking down the problem. 13 | 14 | ## Notes 15 | -------------------------------------------------------------------------------- /errors/EscapedSkolem.md: -------------------------------------------------------------------------------- 1 | # `EscapedSkolem` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | test = do 7 | r <- runST (newSTRef 0) 8 | return 0 9 | ``` 10 | 11 | ## Cause 12 | 13 | Skolem constants are types which only unify with themselves, and a limited range of unification variables. They are used to check polymorphic types, usually when using Rank N Types. 14 | 15 | We say that a skolem _escapes its scope_ when an attempt is made to unify it with a unification variable which was generated outside the scope in which the skolem was generated. 16 | 17 | In the example above, the type of `runST` causes us to check `newSTRef 0` against a polymorphic type, unifying the type of `r` with a skolem constant. However, the type of `r` is fresh, generated outside the scope of `newSTRef 0`, so we see an `EscapedSkolem` error. This is good, because we don't want the reference to leak outside of `runST`. 18 | 19 | ## Fix 20 | 21 | - If you are using the `ST` effect, you might be leaking a reference to a mutable variable. Carefully inspect the types of any values which might leak outside the call to `runST`, and make sure this is not the case. 22 | 23 | ## Notes 24 | 25 | ### `$` and `runST` 26 | 27 | One common pitfall is to use the `runST` or `runPure` functions with the `$` operator. This will often lead to the `EscapedSkolem` error due to instantiation of type variables. Avoid this by using parentheses instead of `$`. 28 | 29 | ### Point free style 30 | 31 | In some cases point free style can also leak type variables. 32 | 33 | ### Impredicative Types 34 | 35 | You can also encounter this error when trying to use impredicative polymorphism, e.g. when a type variable should be instantiated with a polymorphic type. An example could be using a polymorphic type in a data structure, or defining a type alias to a universally quantified type and using it as a type parameter. See [GHC docs](https://ghc.haskell.org/trac/ghc/wiki/ImpredicativePolymorphism) or [this tutorial](http://jozefg.bitbucket.org/posts/2014-12-23-impredicative.html) to learn more about the problem. 36 | -------------------------------------------------------------------------------- /errors/ExpectedType.md: -------------------------------------------------------------------------------- 1 | # `ExpectedType` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ExpectedWildcard.md: -------------------------------------------------------------------------------- 1 | # `ExpectedWildcard` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ExportConflict.md: -------------------------------------------------------------------------------- 1 | # `ExportConflict` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ExprDoesNotHaveType.md: -------------------------------------------------------------------------------- 1 | # `ExprDoesNotHaveType` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ExtraneousClassMember.md: -------------------------------------------------------------------------------- 1 | # `ExtraneousClassMember` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/HidingImport.md: -------------------------------------------------------------------------------- 1 | # `HidingImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | 9 | import Prelude hiding (id) 10 | import Data.Maybe 11 | 12 | z = Just (-1) 13 | ``` 14 | 15 | ## Cause 16 | 17 | A module is imported with the `hiding` form, and there is another implicit import present (which may or may not be `hiding`). 18 | 19 | ## Fix 20 | 21 | Make all but at most one import explicit. In the above example we could make either `Data.Maybe` or `Prelude` explicit, e.g. 22 | 23 | ``` 24 | import Prelude (negate) 25 | ``` 26 | 27 | ## Notes 28 | 29 | [This error is auto-fixable](../guides/Error-Suggestions.md). -------------------------------------------------------------------------------- /errors/HoleInferredType.md: -------------------------------------------------------------------------------- 1 | # `HoleInferredType` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ImplicitImport.md: -------------------------------------------------------------------------------- 1 | # `ImplicitImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | 9 | import Prelude 10 | import Data.Maybe 11 | 12 | z = Just (-1) 13 | ``` 14 | 15 | ## Cause 16 | 17 | A module is imported implicitly (without an explicit import list), and there is another implicit import present (which may or may not be `hiding`). 18 | 19 | ## Fix 20 | 21 | Make all but at most one import explicit. In the above example we could make either `Data.Maybe` or `Prelude` explicit, e.g. 22 | 23 | ``` 24 | import Prelude (negate) 25 | ``` 26 | 27 | ## Notes 28 | 29 | [This error is auto-fixable](../guides/Error-Suggestions.md). -------------------------------------------------------------------------------- /errors/ImplicitQualifiedImport.md: -------------------------------------------------------------------------------- 1 | # `ImplicitQualifiedImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Data.Function as F 9 | import Data.Functor as F 10 | ``` 11 | 12 | ## Cause 13 | 14 | Multiple modules have been imported implicitly with the same qualifier. 15 | 16 | ## Fix 17 | 18 | Use a distinct qualifier, or supply an explicit import list for all but one of the imports in question. 19 | 20 | ## Notes 21 | 22 | As with unqualified implicit imports, the use of the same qualifier for multiple imports without an explicit import 23 | list, the resolution of an identifier may be ambiguous. Just as with unqualified imports, this means that the addition 24 | of an identifier in a dependency may be a breaking change. 25 | 26 | [This error is auto-fixable](../guides/Error-Suggestions.md). 27 | -------------------------------------------------------------------------------- /errors/ImportHidingModule.md: -------------------------------------------------------------------------------- 1 | # `ImportHidingModule` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import B hiding (module A) 9 | ``` 10 | 11 | ## Cause 12 | 13 | An `import` statement has a `hiding` list containing a `module` reference. Hiding imports cannot be used to hide modules. 14 | 15 | ## Fix 16 | 17 | Remove the `hiding` item. 18 | 19 | ## Notes 20 | -------------------------------------------------------------------------------- /errors/IncompleteExhaustivityCheck.md: -------------------------------------------------------------------------------- 1 | # `IncompleteExhaustivityCheck` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/IncorrectAnonymousArgument.md: -------------------------------------------------------------------------------- 1 | # `IncorrectAnonymousArgument` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Example where 7 | 8 | add = (_ + _) 9 | 10 | mapArray = map _ [1, 2, 3] 11 | ``` 12 | 13 | ## Cause 14 | 15 | In an [operator section](https://github.com/purescript/documentation/blob/fc4a9db4b128aa3331e5f990cb1860e59077af31/language/Syntax.md#operator-sections), like `(_ + 1)`, an anonymous argument can be used only once. 16 | 17 | 18 | ## Fix 19 | 20 | In the case of multiple arguments, give them names: 21 | ```purescript 22 | add a b = (a + b) 23 | ``` 24 | or in the case of a normal function: Write the function [as an operator](https://github.com/purescript/documentation/blob/fc4a9db4b128aa3331e5f990cb1860e59077af31/language/Syntax.md#functions-as-operators) using backticks: 25 | ```purescript 26 | mapArray = _ `map` [1, 2, 3] 27 | ``` 28 | 29 | 30 | ## Notes 31 | 32 | - While `_ + _` will give this error; `\a -> a + _` will not 33 | 34 | - If you really want to have multiple anonymous arguments, it can be achieved like this: 35 | ```purescript 36 | add = (((+) $ _) $ _) 37 | ``` 38 | -------------------------------------------------------------------------------- /errors/IncorrectConstructorArity.md: -------------------------------------------------------------------------------- 1 | # `IncorrectConstructorArity` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InfiniteKind.md: -------------------------------------------------------------------------------- 1 | # `InfiniteKind` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InfiniteType.md: -------------------------------------------------------------------------------- 1 | # `InfiniteType` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ErrorExample where 7 | 8 | applySelf x = x x 9 | ``` 10 | 11 | ## Cause 12 | 13 | This fails because x must have a function type, but the domain of the function must be the same type, so we end up with an infinite type `(((... -> r) -> r) -> r) -> r`. 14 | -------------------------------------------------------------------------------- /errors/IntOutOfRange.md: -------------------------------------------------------------------------------- 1 | # `IntOutOfRange` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InvalidDoBind.md: -------------------------------------------------------------------------------- 1 | # `InvalidDoBind` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InvalidDoLet.md: -------------------------------------------------------------------------------- 1 | # `InvalidDoLet` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InvalidFFIIdentifier.md: -------------------------------------------------------------------------------- 1 | # `InvalidFFIIdentifier` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/InvalidInstanceHead.md: -------------------------------------------------------------------------------- 1 | # `InvalidInstanceHead` Error 2 | 3 | ## Example 4 | 5 | As of 0.11.6, the `InvalidInstanceHead` error has been added to the 6 | purescript compiler. The error can be produced using the following: 7 | 8 | ```purescript 9 | module InvalidInstanceHead where 10 | 11 | class ClassWithInvalidInstanceHead (x :: # Type) 12 | 13 | instance FailingExample :: ClassWithInvalidInstanceHead () 14 | ... 15 | ``` 16 | 17 | ## Cause 18 | 19 | Normally, when you see this error, it's because you're trying to write an 20 | `instance` of a given `class` that pattern matches on some **row type**. The 21 | issue here is that there isn't really a sensible way to match on row. There 22 | are, however, ways to get around this limitation. 23 | 24 | ## Fix 25 | 26 | With the arrival of [`purescript-typelevel-prelude`](https://github.com/purescript/purescript-typelevel-prelude) 27 | 2.3.0 came the introduction of `RowToList` and its related classes. The 28 | basic idea is that you can convert a row type to a type-level cons list of its 29 | entries. For example: 30 | 31 | ```purescript 32 | -- ROW LIST 33 | 34 | RowToList () Nil 35 | RowToList (a :: A) (Cons "a" A Nil) 36 | RowToList (a :: A, b :: B) (Cons "a" A (Cons "b" B Nil)) 37 | ``` 38 | 39 | The `RowToList` constraint allows us to derive, from a row type, the `RowList` 40 | that complements it. The keys of the `RowList` are alphabetically ordered, which 41 | allows us to manipulate row types in a deterministic way. If your instance heads 42 | pattern match on `RowList` instead of `# Type`, this error goes away. 43 | 44 | ## Worked Example 45 | 46 | Let's imagine a class that we use to assert that a record is homogenous. Or, in 47 | simpler terms, all the fields in the record have the same type. 48 | 49 | ```purescript 50 | class IsHomogenousRowType (rowType :: # Type) 51 | ``` 52 | 53 | Now, as we've seen earlier, we can't just pattern-match on this in its current 54 | state; we need to convert it to a `RowList`. How do we do that? 55 | 56 | ```purescript 57 | instance isHomogenousImpl 58 | :: ( RowToList rowType rowList 59 | , IsHomogenousRowList rowList a 60 | ) 61 | => IsHomogenousRecord rowType 62 | ``` 63 | 64 | Here, we say that, "if you can find me a `RowList` representation for my record 65 | that satisfies `IsHomogenousRow`, then this record is good to go". Notice how 66 | we're "pattern matching" on the left side of `RowToList` - we don't know what 67 | `la` is, but we trust the compiler to iron out that little detail for us. 68 | 69 | Now we implement `IsHomogenousRowList`. The type parameter `list` is the `RowList` 70 | we want to check for homogeneously-typed values, which all have type `a`. 71 | 72 | ```purescript 73 | class IsHomogenousRowList (list :: RowList) a | list -> a 74 | ``` 75 | 76 | Because we're now dealing with a `RowList`, we can pattern match and avoid those 77 | pesky errors about instance heads. Our functional dependency here says that, "if 78 | you can give me the type of `list`, I can always give you the type of `a`". The 79 | first example of this is a special case: 80 | 81 | ```purescript 82 | instance isHomogenousRowListImplEmpty 83 | :: IsHomogenousRowList Nil Unit 84 | ``` 85 | 86 | We just need to pick a type to use when we're dealing with an empty row; unit is 87 | inoffensive enough, so we'll go with that. Next up, what happens if we only have 88 | one entry? 89 | 90 | ```purescript 91 | instance isHomogenousRowListImplNonEmpty 92 | :: IsHomogenousRowList (Cons k a Nil) a 93 | ``` 94 | 95 | When we have a singleton object, the instance is trivial; the record is always 96 | homogenous. All we're doing here is saying that the row is homogenous if we can 97 | find a type that matches the type of the single key. Easy! 98 | 99 | Finally, we have to deal with the other cases. This can be generalised: 100 | 101 | ```purescript 102 | instance isHomogenousRowListImplReallyNonEmpty 103 | :: IsHomogenousRowList la a 104 | => IsHomogenousRowList (Cons k a la) a 105 | ``` 106 | 107 | Here, we match the row as `Cons k a la`. If `la` is a homogenous row of type `a` 108 | and `a` is the type of our row head, then we're all good! Success! Notice we end 109 | up with two base cases here: an empty record and a singleton. Why? Well, if we 110 | had only the empty one, it would only work for records where all fields were of 111 | type `Unit`. Think about why this is. 112 | 113 | At this point, everything would look as though it should work, right? We can 114 | write a little helper function to that class stuff so we can use it in pratice: 115 | 116 | ```purescript 117 | validateHomogeneity 118 | :: forall ra 119 | . IsHomogenousRecord ra 120 | => Record ra 121 | -> Record ra 122 | validateHomogeneity = id 123 | ``` 124 | 125 | Now, if we call `validateHomogeneity` on our record, it will be checked at 126 | *compile time*. With `RowToList`, we recover all the ability to pattern match 127 | on row types that we would otherwise have lost. 128 | 129 | If you'd like to play around with the examples above, you can use TryPureScript 130 | to play with it in an [interactive 131 | Gist](http://try.purescript.org/?gist=cf4a032ae0741b7c21994c93cfb3c633). 132 | -------------------------------------------------------------------------------- /errors/InvalidNewtype.md: -------------------------------------------------------------------------------- 1 | # `InvalidNewtype` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | newtype NotIdentity a = a 7 | 8 | newtype NotTuple a b = NotTuple a b 9 | ``` 10 | 11 | ## Cause 12 | 13 | Newtypes must define a single constructor with a single argument, so the two 14 | most common sources of this error are having multiple arguments (like a `Tuple`) 15 | or forgetting to provide a constructor. 16 | 17 | ## Fix 18 | 19 | - If you need multiple arguments, consider using a newtype around a record or `Tuple`: 20 | 21 | ```purescript 22 | newtype RecordTuple a b = RecordTuple {fst :: a, snd :: b} 23 | ``` 24 | -------------------------------------------------------------------------------- /errors/InvalidNewtypeInstance.md: -------------------------------------------------------------------------------- 1 | # `InvalidNewtypeInstance` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | newtype ManyErrors e a = ManyErrors (Either e (Maybe a)) 7 | 8 | derive newtype instance manyErrorsFunctor :: Functor (ManyErrors e) 9 | ``` 10 | 11 | ## Cause 12 | 13 | While `ManyErrors` is a valid newtype, its underlying representation is not a 14 | type for which a `Functor` instance already exists. Most causes of this error are 15 | due to the newtype being some composition of other types (in our case, `Either` 16 | and `Maybe`) instead of just one type. 17 | 18 | ## Fix 19 | 20 | - In many cases you can use existing higher-order newtypes that already have the 21 | relevant instances defined. For example, we could have done the following without 22 | getting an error: 23 | 24 | ```purescript 25 | import Data.Functor.Compose (Compose) 26 | 27 | newtype ManyErrors e a = ManyErrors (Compose (Either e) Maybe a) 28 | 29 | derive newtype instance manyErrorsFunctor :: Functor (ManyErrors e) 30 | ``` 31 | 32 | This works because `Compose f g` is a functor whenever `f` and `g` are functors. 33 | 34 | Otherwise, we would need to explicitly write the instance ourselves. 35 | 36 | ## Notes 37 | 38 | - If the underlying type does not have an instance to derive, you will instead 39 | get a [NoInstanceFound](https://github.com/purescript/documentation/blob/master/errors/NoInstanceFound.md) 40 | error. 41 | -------------------------------------------------------------------------------- /errors/InvalidOperatorInBinder.md: -------------------------------------------------------------------------------- 1 | # `InvalidOperatorInBinder` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/KindsDoNotUnify.md: -------------------------------------------------------------------------------- 1 | # `KindsDoNotUnify` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | > import Type.Proxy 7 | > x = Proxy :: Proxy Array 8 | Error found: 9 | in module $PSCI 10 | at line 1, column 5 - line 1, column 24 11 | 12 | Could not match kind 13 | 14 | Type 15 | 16 | with kind 17 | 18 | Type -> Type 19 | 20 | 21 | while checking the kind of Proxy Array 22 | ``` 23 | 24 | ## Cause 25 | 26 | This error occurs when the compiler requires two _kinds_ to be equal, but they are not equal. 27 | 28 | In the example above, the type constructor `Proxy` takes an argument of kind `Type`, but `Array` has kind `Type -> Type`, hence the error message. 29 | 30 | ## Fix 31 | 32 | - Look at the information in the error message to find the type with the offending kind. 33 | 34 | ## Notes 35 | 36 | ### Order of Error Message 37 | 38 | In the `Proxy Array` example above it is unclear if `Type` refers to the expected kind and `Type -> Type` refers to the actual kind found on line 1 or vice-versa. The current implementation of Purescript sometimes presents the expected value first and other times presents the actual value first. In this sense the presentation of this error is inconsistent, so please don't read any order into the error message. 39 | 40 | ### Additional/Missing Type Arguments 41 | 42 | This error can occur when a type argument is missing, or an additional type argument is provided: 43 | 44 | ```purescript 45 | instance functorArray :: Functor (Array a) where 46 | ... 47 | ``` 48 | 49 | This results in a kind error, due to the additional type argument `a` passed to `Array` (in `Functor (Array a)`). The solution is to use `Functor Array` instead. 50 | -------------------------------------------------------------------------------- /errors/MisleadingEmptyTypeImport.md: -------------------------------------------------------------------------------- 1 | # `MisleadingEmptyTypeImport` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/MissingClassMember.md: -------------------------------------------------------------------------------- 1 | # `MissingClassMember` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/MissingFFIImplementations.md: -------------------------------------------------------------------------------- 1 | # `MissingFFIImplementations` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/MissingFFIModule.md: -------------------------------------------------------------------------------- 1 | # `MissingFFIModule` Error 2 | 3 | ## Cause 4 | 5 | This error occurs if a module uses any foreign imports, but a foreign module could not be found. 6 | 7 | Usually, this means that you declared a foreign import in the PureScript module but didn't create a corresponding FFI module yet. 8 | 9 | ## Fix 10 | 11 | - Check that the foreign module with the matching name exists. The PureScript compiler finds FFI modules by taking the source file path, and replacing the `.purs` extension with `.js`. 12 | 13 | ## Notes 14 | -------------------------------------------------------------------------------- /errors/MissingTypeDeclaration.md: -------------------------------------------------------------------------------- 1 | # `MissingTypeDeclaration` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Main where 7 | import Effect.Console (log) 8 | 9 | main = log "No type annotation has been provided." 10 | ``` 11 | 12 | ## Cause 13 | 14 | This warning is issued when a top-level declaration does not have a type annotation. The vast majority of types in PureScript code are inferrable, so it's relatively rare that the absence of a type annotation has much of an effect on compilation, but it is considered good practice to add annotations to top-level declarations anyway (as a form of documentation). 15 | 16 | ## Fix 17 | 18 | Add a type annotation: 19 | 20 | ```purescript 21 | module Main where 22 | import Effect (Effect) 23 | import Effect.Console (log) 24 | 25 | main :: Effect Unit 26 | main = log "A type annotation has been provided!" 27 | ``` 28 | 29 | ## Notes 30 | 31 | Many of [the PureScript text editor plugins](/ecosystem/Editor-and-tool-support.md) can save you the effort of writing type annotations by filling in the types for you. 32 | 33 | Declarations which are not at the top level, such as those contained within `let` or `where` clauses, are not considered as important to annotate with types, and so the compiler does not issue warnings when these declarations are not annotated. The following example compiles without warnings, even though `message` has not been given a type annotation: 34 | 35 | ```purescript 36 | module Main where 37 | import Effect.Console (log) 38 | 39 | main :: Effect Unit 40 | main = 41 | let 42 | message = "Hello, world!" 43 | in 44 | log message 45 | ``` 46 | -------------------------------------------------------------------------------- /errors/MixedAssociativityError.md: -------------------------------------------------------------------------------- 1 | # `MixedAssociativityError` 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Prelude ((<$>), (==)) 9 | 10 | feq f x y = f <$> x == f <$> y 11 | ``` 12 | 13 | Result: 14 | ``` 15 | Cannot parse an expression that uses operators of the same precedence but mixed associativity: 16 | 17 | Data.Functor.(<$>) is infixl 18 | Data.Eq.(==) is infix 19 | 20 | Use parentheses to resolve this ambiguity. 21 | ``` 22 | 23 | ## Cause 24 | 25 | This error arises when an expression involves operators of the same precedence but different associativities. In this example, `<$>` is `infixl 4`, that is, left-associative with precedence 4, whereas `==` is `infix 4`, that is, non-associative with precedence 4. The compiler is unable to determine how to bracket this expression because of the precendences and associativities involved; either the associativities must be the same or the precedences must be different. See [Syntax - Binary Operators](../language/Syntax.md#binary-operators) in the language reference for more information. 26 | 27 | ## Fix 28 | 29 | The most appropriate fix is usually to add brackets to remove the ambiguity: 30 | 31 | ``` 32 | feq f x y = (f <$> x) == (f <$> y) 33 | ``` 34 | 35 | An alternative fix is to change the precedence of one of the operators, in order to allow the expression to be parsed without adding parentheses. 36 | -------------------------------------------------------------------------------- /errors/ModuleNotFound.md: -------------------------------------------------------------------------------- 1 | # `ModuleNotFound` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Example where 7 | 8 | -- Notice the typo here: the module we are after is called Control.Monad.Eff.Console. 9 | import Contorl.Monad.Eff.Console (log) 10 | 11 | main = log "Hello, world!" 12 | ``` 13 | 14 | ## Cause 15 | 16 | You might see this error because you have attempted to import a module which the compiler was unable to find, or because you mistyped the name of a module. 17 | 18 | ## Fix 19 | 20 | Check that: 21 | 22 | - you have spelled the name of the module correctly, 23 | - if the module comes from a library, that you have installed that library in your project, 24 | - you have supplied the filename of the module to `purs build` on the command line (note that build tools, such as `webpack` or `pulp`, should generally take care of this for you; if in doubt, check their documentation). 25 | 26 | If you know which module you are looking for but are unsure which library it comes from, you can search for it on . 27 | -------------------------------------------------------------------------------- /errors/MultipleFFIModules.md: -------------------------------------------------------------------------------- 1 | # `MultipleFFIModules` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/MultipleTypeOpFixities.md: -------------------------------------------------------------------------------- 1 | # `MultipleTypeOpFixities` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/MultipleValueOpFixities.md: -------------------------------------------------------------------------------- 1 | # `MultipleValueOpFixities` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/NameIsUndefined.md: -------------------------------------------------------------------------------- 1 | # `NameIsUndefined` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/NoInstanceFound.md: -------------------------------------------------------------------------------- 1 | # `NoInstanceFound` Error 2 | 3 | ## Example 4 | 5 | ``` 6 | > data Foo = Foo 7 | > show Foo 8 | No type class instance found for Data.Show.Show Foo 9 | 10 | > data Fooy a = Fooy a 11 | > data Bar a = Bar (Fooy a) 12 | > derive instance functorBar :: Functor Bar 13 | No type class instance was found for Data.Functor.Functor Fooy 14 | ``` 15 | 16 | ## Causes and Fixes 17 | 18 | This error occurs when the type-checker can't find an instance of a type class for a data type where it expects or requires one. 19 | 20 | Some situations in which this can occur: 21 | 22 | ### Can't find instance 23 | 24 | This error is caused when a function has a type signature having a type class constraint on a type, but the type-checker can't find an instance of the type class for that type. 25 | 26 | In the `show Foo` example above, we use `show`, which is a member of the `Show` type class. Its type is 27 | 28 | ```purescript 29 | show :: forall a. Show a => a -> String 30 | ``` 31 | 32 | This means that `show` takes a value of some type `a` and returns a `String`, with the constraint that `a` must have a `Show` instance. The "NoInstanceFound" error will arise if the compiler can't find a `Show` instance for the `Foo` data type. 33 | 34 | This can be fixed by adding an instance for the relevant type. To fix the earlier example: 35 | 36 | ``` 37 | > instance showFoo :: Show Foo where show Foo = "Foo" 38 | > show Foo 39 | "Foo" 40 | ``` 41 | 42 | ### Ambiguous types 43 | 44 | This error can arise in situations where the compiler is not able to solve a constraint due to ambiguous types. This is demonstrated in the following example in which no concrete type appears in the function's definition; it only uses type class methods. The compiler must be given a concrete type, or be able to infer it, to choose a type class instance. 45 | 46 | ```purescript 47 | bad = show mempty 48 | ``` 49 | 50 | To fix this, consider adding a type signature: 51 | 52 | ```purescript 53 | better = show (mempty :: String) 54 | ``` 55 | 56 | ### Partial type class & non-exhaustive patterns 57 | 58 | This error can occur if your code fails to propagate `Partial` constraints properly. For an introduction to the `Partial` type class, please see the [purescript-partial library](https://pursuit.purescript.org/packages/purescript-partial). 59 | 60 | As an example of this situation, consider the following function definition: 61 | 62 | ``` 63 | > f 0 = 0 64 | ``` 65 | 66 | This function does not handle all possible inputs: it is undefined for all inputs other than zero. Such functions are called *partial* and the compiler will infer a `Partial` constraint: 67 | 68 | ``` 69 | > :type f 70 | (Partial) => Int -> Int 71 | ``` 72 | 73 | If we try to use the function directly, we will get a `NoInstanceFound` error: 74 | 75 | ``` 76 | > g = f 1 77 | 78 | A case expression could not be determined to cover all inputs. 79 | The following additional cases are required to cover all inputs: 80 | 81 | _ 82 | 83 | Alternatively, add a Partial constraint to the type of the enclosing value. 84 | ``` 85 | 86 | This error can be removed by modifying the definition of `f` to handle all possible inputs. 87 | -------------------------------------------------------------------------------- /errors/NonAssociativeError.md: -------------------------------------------------------------------------------- 1 | # `NonAssociativeError` 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Prelude ((==), (/=)) 9 | 10 | example = true == false /= true 11 | ``` 12 | 13 | Result: 14 | ``` 15 | Cannot parse an expression that uses multiple non-associative operators of the same precedence: 16 | 17 | Data.Eq.(/=) 18 | Data.Eq.(==) 19 | 20 | Use parentheses to resolve this ambiguity. 21 | ``` 22 | 23 | ## Cause 24 | 25 | This error arises when a group of non-associative operators with the same precedence are used in such a way that the compiler cannot be sure how to bracket them unambiguously. In the example above, `==` and `/=` from Prelude are both declared as `infix 4` (non-associative, precedence 4), so it's not clear whether this expression should be bracketed as `(true == false) /= true` or `true == (false /= true)`. 26 | 27 | This error will not arise in the case of repeated applications of operators which have been declared as `infixl` or `infixr`, as in this case, the fixity declaration removes the ambiguity by specifying which way expressions should be bracketed. See [Syntax - Binary Operators](../language/Syntax.md#binary-operators) in the language reference for more information. 28 | 29 | ## Fix 30 | 31 | The most appropriate fix is usually to add brackets to remove the ambiguity: 32 | 33 | ```purescript 34 | (true == false) /= true 35 | ``` 36 | 37 | An alternative fix is to change one or more of the operators' fixities or precedences so that the compiler can determine how expressions involving these operators should be bracketed without extra guidance. 38 | -------------------------------------------------------------------------------- /errors/OrphanInstance.md: -------------------------------------------------------------------------------- 1 | # `OrphanInstance` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module A where 7 | 8 | class SomeClass a 9 | ``` 10 | 11 | ```purescript 12 | module B where 13 | 14 | data SomeData 15 | ``` 16 | 17 | ```purescript 18 | module C where 19 | 20 | import A 21 | import B 22 | 23 | instance someInstance :: SomeClass SomeData 24 | ``` 25 | 26 | ## Cause 27 | 28 | This error occurs when an instance is declared outside of the module that declares the class it is for, and also none of the instance's types are declared in the same module. 29 | 30 | Above, `someInstance` is an orphan here as it is defined in a module separate from both `SomeData` and `SomeClass`. 31 | 32 | ## Fix 33 | 34 | - If possible, move the instance into an allowed module. 35 | - Consider adding a `newtype`, and defining the instance in the same module as the `newtype`. 36 | 37 | ## Notes 38 | 39 | ### Orphan Instances with Functional Dependencies 40 | 41 | When using type classes involving functional dependencies, the rules for orphan instances are a little more complicated. They are explained in [this blog post](https://liamgoodacre.github.io/purescript/type/class/instance/orphan/functional/dependencies/2017/01/22/purescript-orphan-instance-detection.html). 42 | -------------------------------------------------------------------------------- /errors/OrphanTypeDeclaration.md: -------------------------------------------------------------------------------- 1 | # `OrphanTypeDeclaration` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/OverlappingArgNames.md: -------------------------------------------------------------------------------- 1 | # `OverlappingArgNames` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | > f x x = x 7 | Error found: 8 | in module $PSCI 9 | at line 1, column 5 - line 1, column 13 10 | 11 | Overlapping names in function/binder in declaration f 12 | ``` 13 | 14 | ## Cause 15 | 16 | This error occurs when you attempt to bind the same variable to different function arguments. 17 | 18 | ## Fix 19 | 20 | - Rename one of the duplicate function arguments. 21 | 22 | ## Notes 23 | -------------------------------------------------------------------------------- /errors/OverlappingInstances.md: -------------------------------------------------------------------------------- 1 | # `OverlappingInstances` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/OverlappingNamesInLet.md: -------------------------------------------------------------------------------- 1 | # `OverlappingNamesInLet` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/OverlappingPattern.md: -------------------------------------------------------------------------------- 1 | # `OverlappingPattern` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | not :: Boolean -> Boolean 7 | not true = false 8 | not _ = true 9 | not false = true 10 | ``` 11 | 12 | ## Cause 13 | 14 | This error occurs when a pattern matching definition has **redundant** patterns, i.e., overlapping clauses. 15 | 16 | In the example, notice that the third case is redundant (that is, unreachable), as it is covered by the second case (which covers all remaining cases). 17 | 18 | ## Fix 19 | 20 | - Remove any redundant cases from the declaration. 21 | 22 | ## Notes 23 | -------------------------------------------------------------------------------- /errors/PartiallyAppliedSynonym.md: -------------------------------------------------------------------------------- 1 | # `PartiallyAppliedSynonym` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | newtype UserNT f = UserNT { firstName :: f String } 9 | type TypeIdentity t = t 10 | -- The following produces a `PartiallyAppliedSynonym` error. 11 | u :: UserNT TypeIdentity 12 | u = UserNT { firstName: "" } 13 | 14 | ----- Another example 15 | 16 | data Const a b = Const a 17 | data IdentityF f a = IdentityF (f a) 18 | 19 | ok :: IdentityF (Const Int) Unit 20 | ok = IdentityF (Const 5) 21 | 22 | -- A, B, and X are all synonyms for the same thing. 23 | type A = Const 24 | 25 | alsoOk :: IdentityF (A Int) Unit 26 | alsoOk = IdentityF (Const 5) 27 | 28 | type B a = Const a 29 | 30 | alsoAlsoOk :: IdentityF (B Int) Unit 31 | alsoAlsoOk = IdentityF (Const 5) 32 | 33 | type X a b = Const a b 34 | 35 | -- The X type synonym is partially applied here. 36 | error :: IdentityF (X Int) Unit 37 | error = IdentityF (Const 5) 38 | ``` 39 | 40 | ## Cause 41 | 42 | A type synonym has been partially applied. To properly use a type synonym having type parameters, like `type B a` or `type TypeIdentity a`, you must apply it to a type parameter at every location in the program, like `B Int` or `TypeIdentity Int`. 43 | 44 | To understand the problem, it may be helpful to review the relevant difference between a "type synonym" and a "data type". A type synonym is effectively a macro, a substitution which is performed after parsing into an AST and before type-checking and compilation, while a data type is a proper entity through the compilation process. Because of this, a type synonym has much more restricted use, while a data type enjoys additional flexibility, such as the ability to be partially applied. 45 | 46 | Interestingly, a type synonym *can* be partially applied in the context of a type synonym, however. For example: 47 | 48 | ```purescript 49 | type UserT' f = { firstName :: f String } 50 | u' :: UserT' TypeIdentity 51 | u' = { firstName: "test" } 52 | ``` 53 | 54 | ## Fix 55 | 56 | Reconsider whether you want to use a type synonym for that particular type declaration, or whether to a data type is more appropriate. 57 | 58 | In the example above, if you want to use the type synonym `TypeIdentity`, you will need to apply it to another type synonym to produce a concrete type. That concrete type can then be used in a newtype or a function type signature. 59 | 60 | ```purescript 61 | type UserT' f = { firstName :: f String } 62 | newtype UserNT' = UserNT' (UserT' TypeIdentity) 63 | u :: UserNT' 64 | u = UserNT' { firstName: "test" } 65 | newtype UserNT'Maybe = UserNT'Maybe (UserT' Maybe) 66 | um :: UserNT'Maybe 67 | um = UserNT'Maybe { firstName: Just "test" } 68 | ``` 69 | 70 | And to fix the second example, we can't simply fully apply `X`, as that would produce a kind error, `Could not match kind Type -> Type with kind Type`. The `f` in `IdentityF f a` needs to be kind `Type -> Type`, but here it is kind `Type`. The most appropriate solution is to simply use `A` or `B` as the type synonym, as demonstrated in `alsoOk` and `alsoAlsoOk`. 71 | 72 | ## Notes 73 | 74 | Eta-expanding makes it impossible to use the synonym in some situations in which it would otherwise work, and unlike some other restrictions we impose on ourselves using the type system, this one is never useful - it only prevents you doing things you might want to do, not things you might want to avoid. 75 | 76 | An example, from transformers, if State was defined as follows, it would be impossible to use `State` in some situations. 77 | 78 | ``` 79 | -- note the `a`, in the library this is omitted on both sides 80 | type State s a = StateT s Identity a 81 | ```` 82 | 83 | For example, the following situation is one in which we would want to use `State`. When stacking monad transformers, only the "top" of the stack has its `a`, its second type parameter, provided, and the "lower" layers are used to specify its `m`, its monad. 84 | 85 | ``` 86 | -- If `State` is defined as above, the following would fail, 87 | -- as the type synonym is only receiving an argument for `s`, the `MyState` type. 88 | newtype App1 a = App1 (ExceptT MyError (State MyState) a) 89 | newtype App2 a = App2 (WriterT MyLog (ExceptT MyError (State MyState)) a) 90 | ``` 91 | 92 | By defining it as `type State s a`, we are saying it requires two type arguments, but in both of the above cases, we apply `MyState` to `State`, which is just one type argument. Because the example didn't include a type for `a` when using the `State` synonym, it is left partially applied, 93 | 94 | Related to this, purescript/purescript#2691 is an issue which requests adding a warning for type synonyms which can be eta-reduced. 95 | -------------------------------------------------------------------------------- /errors/PossiblyInfiniteInstance.md: -------------------------------------------------------------------------------- 1 | # `PossiblyInfiniteInstance` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/PropertyIsMissing.md: -------------------------------------------------------------------------------- 1 | # `PropertyIsMissing` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/RedefinedIdent.md: -------------------------------------------------------------------------------- 1 | # `RedefinedIdent` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Example where 7 | 8 | a = 3 9 | 10 | a = 5 11 | 12 | ``` 13 | 14 | ## Cause 15 | 16 | You have defined a value with the same name multiple times. 17 | 18 | ## Fix 19 | 20 | - Rename one of the variables. In this example: 21 | ```purescript 22 | a = 3 23 | 24 | a' = 5 25 | ``` 26 | 27 | ## Notes 28 | 29 | - This error also occurs if you have multiple clauses for a function, where you misspelled the function name once. For Example: 30 | ```purescript 31 | bar [] = 10 32 | barr [2] = 2 33 | bar x = length x 34 | ``` 35 | -------------------------------------------------------------------------------- /errors/ScopeConflict.md: -------------------------------------------------------------------------------- 1 | # `ScopeConflict` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ScopeConflict where 7 | 8 | -- `Prelude` exports a function called `id` 9 | import Prelude 10 | 11 | id :: Number 12 | id = 1 13 | ``` 14 | 15 | ## Cause 16 | 17 | The `ScopeConflict` error occurs when an attempt is made to define a value or other name when the same name is already in scope. 18 | 19 | ## Fix 20 | 21 | - Hide the problematic imports with a `hiding` list: 22 | 23 | ```purescript 24 | module NoScopeConflict where 25 | 26 | import Prelude hiding (id) 27 | 28 | id :: Number 29 | id = 1 30 | ``` 31 | 32 | - Alternatively, import the conflicting module using the `as` keyword: 33 | 34 | ```purescript 35 | module NoScopeConflict where 36 | 37 | import Prelude as P 38 | 39 | id :: Number 40 | id = 1 41 | ``` 42 | 43 | ## Notes 44 | 45 | A common case this arises at the moment is if PureScript 0.11.x libraries are used with the 0.10.x compiler. The resulting error is: 46 | 47 | ``` 48 | Conflicting definitions are in scope for kind Effect from the following modules: 49 | 50 | Control.Monad.Eff 51 | Prim 52 | ``` 53 | 54 | To fix this either downgrade the libraries, or upgrade the compiler. 55 | -------------------------------------------------------------------------------- /errors/ScopeShadowing.md: -------------------------------------------------------------------------------- 1 | # `ScopeShadowing` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/ShadowedName.md: -------------------------------------------------------------------------------- 1 | # `ShadowedName` Warning 2 | 3 | ## Example 4 | 5 | ``` 6 | > x = let x = 1 in x 7 | 8 | Warning 1 of 1: 9 | 10 | at line 1, column 1 - line 3, column 7 11 | 12 | Name x was shadowed. 13 | 14 | in value declaration x 15 | ``` 16 | 17 | ## Cause 18 | 19 | This warning occurs when a name is brought into scope, but that name is already defined in the current scope. In the example above, `x` is used to refer to both the inner and outer `let` binding. 20 | 21 | PureScript warns in this case because multiple uses of the same name might make it easy to refer to the wrong value. 22 | 23 | ## Fix 24 | 25 | - Consider renaming one or other occurrence of the name. 26 | 27 | ## Notes 28 | -------------------------------------------------------------------------------- /errors/ShadowedTypeVar.md: -------------------------------------------------------------------------------- 1 | # `ShadowedTypeVar` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/Template.md: -------------------------------------------------------------------------------- 1 | # `ErrorCode` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/TransitiveDctorExportError.md: -------------------------------------------------------------------------------- 1 | # `TransitiveDctorExportError` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/TransitiveExportError.md: -------------------------------------------------------------------------------- 1 | # `TransitiveExportError` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module Example (foo) where 7 | 8 | data Bar 9 | 10 | foo :: Bar -> Bar 11 | foo x = x 12 | ``` 13 | 14 | ## Cause 15 | 16 | This error occurs when one name is exported, but exporting that name requires some other name(s) to also be exported. 17 | 18 | The example above generates the following error: 19 | 20 | ```text 21 | Error in module M: 22 | 23 | An export for foo requires the following to also be exported: 24 | 25 | Bar 26 | ``` 27 | 28 | PureScript requires any types appearing inside a type declaration to also be exported. Similar restrictions apply to things like type classes and type class member exports. 29 | 30 | ## Fix 31 | 32 | - Follow the instructions in the error, and add the required names to the list of exports: 33 | 34 | ```purescript 35 | module Example (foo, Bar) where 36 | 37 | data Bar 38 | 39 | foo :: Bar -> Bar 40 | foo x = x 41 | ``` 42 | 43 | ## Notes 44 | 45 | See the [language guide page on modules](../language/Modules.md#module-exports). 46 | -------------------------------------------------------------------------------- /errors/TypeSynonymInstance.md: -------------------------------------------------------------------------------- 1 | # `TypeSynonymInstance` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module TypeSynonymInstanceError where 7 | import Prelude 8 | 9 | type Mass = Number 10 | 11 | instance showMass :: Show Mass where 12 | show mass = "Mass: " <> show mass <> "kg" 13 | ``` 14 | 15 | ## Cause 16 | 17 | [Type synonyms](../language/Types.md#type-synonyms) are merely aliases (usually created to avoid verbose type annotations) and do not declare a new unique type. It is still possible to use the synonym and its equivalent type interchangeably. 18 | 19 | Since every value that structually matches the type synonym could be considered of the same type, it is not allowed to implement [type classes](../language/Type-Classes.md) based on type synonyms. 20 | 21 | ## Fix 22 | 23 | A [newtype](../language/Types.md#newtypes) declaration generates a brand new type instead of introducing a synonym for an existing type. Newtypes can have type class instances declared for them: 24 | 25 | ```purescript 26 | newtype Mass = Mass Number 27 | 28 | instance showMass :: Show Mass where 29 | show (Mass mass) = "Mass: " <> show mass <> "kg" 30 | ``` 31 | 32 | ## Notes 33 | 34 | The same error occurs when the aliased type is a record: 35 | 36 | ```purescript 37 | type Point = { x :: Number, y :: Number } 38 | 39 | instance showPoint :: Show Point where 40 | show p = "Point " <> show p.x <> ", " <> show p.y 41 | ``` 42 | -------------------------------------------------------------------------------- /errors/TypesDoNotUnify.md: -------------------------------------------------------------------------------- 1 | # `TypesDoNotUnify` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | > 1 == "test" 7 | Error found: 8 | in module $PSCI 9 | at line 1, column 6 - line 1, column 6 10 | 11 | Could not match type 12 | 13 | String 14 | 15 | with type 16 | 17 | Int 18 | 19 | while checking that type String 20 | is at least as general as type Int 21 | while checking that expression "test" 22 | has type Int 23 | ``` 24 | 25 | ## Cause 26 | 27 | This error occurs when two types are required to be equal, but the type checker is unable to verify that they are equal. 28 | 29 | In the example above, the types `String` and `Int` can never be made equal, hence the error. 30 | 31 | ## Fix 32 | 33 | - Look carefully at the error, especially the information at the end. Usually, it will help to narrow down the offending expression. For example, in the error message above, we are told that the error occurred "while checking that expression `"test"` has type `Int`". 34 | 35 | ## Notes 36 | ### Arrays 37 | 38 | Unlike in JavaScript, all elements of a PureScript array must be the same type. Otherwise the types will fail unification when being matched by [type inference](https://en.wikipedia.org/wiki/Unification_(computer_science)#Application:_Type_inference). For example, ```[true, false]``` or ```[1, 2, 3]``` work fine but ```[1, false]``` does not. 39 | 40 | ### Another Example 41 | 42 | ```purescript 43 | f :: Int -> Int 44 | f x = x + 1 45 | 46 | g :: Boolean -> Boolean 47 | g x = x || true 48 | 49 | h = g <<< f 50 | ``` 51 | 52 | The type of `(<<<)` (that is, function composition) is 53 | 54 | ```purescript 55 | forall a b c. (b -> c) -> (a -> b) -> (a -> c) 56 | ``` 57 | 58 | For the right hand side of `h` to type-check, we need to find types `a`, `b`, and `c` such that the types match up. That is, we need to find a choice of `a`, `b`, and `c` such that: 59 | 60 | - `b = Boolean` (from the argument type of `g`) 61 | - `c = Boolean` (from the return type of `g`) 62 | - `a = Number` (from the argument type of `f`) 63 | - `b = Number` (from the return type of `f`). 64 | 65 | `b` can not be `Boolean` and `Number` at the same time, so this system of equations is not satisfiable, and the type checker rejects the program. 66 | 67 | ### Matching Labels in Rows 68 | 69 | Note that for row types (e.g. in objects or effects) to be equal, not only the types, but the labels themselves must match identically. 70 | -------------------------------------------------------------------------------- /errors/UndefinedTypeVariable.md: -------------------------------------------------------------------------------- 1 | # `UndefinedTypeVariable` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | id :: a -> a 7 | id x = x 8 | ``` 9 | 10 | ## Cause 11 | 12 | This error occurs when an undefined type variable appears in a type signature. 13 | 14 | In the example, the type variable `a` is undefined. 15 | 16 | Note that PureScript requires all type variables to be defined in type signatures, unlike in Haskell. See also [Differences from Haskell](../language/Differences-from-Haskell.md). 17 | 18 | ## Fix 19 | 20 | - Check the spelling of any type variables. 21 | - A possible fix is to introduce the variable using a `forall` quantifier: 22 | 23 | ```purescript 24 | id :: forall a. a -> a 25 | id x = x 26 | ``` 27 | 28 | ## Notes 29 | -------------------------------------------------------------------------------- /errors/UnknownClass.md: -------------------------------------------------------------------------------- 1 | # `UnknownClass` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnknownExport.md: -------------------------------------------------------------------------------- 1 | # `UnknownExport` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnknownExportDataConstructor.md: -------------------------------------------------------------------------------- 1 | # `UnknownExportDataConstructor` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnknownImport.md: -------------------------------------------------------------------------------- 1 | # `UnknownImport` Error 2 | 3 | ## Example 4 | 5 | ``` 6 | > import Prelude (doesNotExist) 7 | Error found: 8 | in module $PSCI 9 | at line 1, column 17 - line 1, column 29 10 | 11 | Cannot import value doesNotExist from module Prelude 12 | It either does not exist or the module does not export it. 13 | ``` 14 | 15 | ## Cause 16 | 17 | This error occurs when trying to import a name which does not exist. 18 | 19 | ## Fix 20 | 21 | - Check spelling of any imported names. 22 | - Check dependencies to make sure you are using the correct versions. You can use [Pursuit](https://pursuit.purescript.org/) to check which package versions define the names you are trying to import. 23 | 24 | ## Notes 25 | -------------------------------------------------------------------------------- /errors/UnknownImportDataConstructor.md: -------------------------------------------------------------------------------- 1 | # `UnknownImportDataConstructor` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnknownName.md: -------------------------------------------------------------------------------- 1 | # `UnknownName` Error 2 | 3 | ## Example 4 | 5 | ``` 6 | > import Prelude 7 | > x = y + 1 8 | 9 | Error found: 10 | in module $PSCI 11 | at line 1, column 13 - line 1, column 14 12 | 13 | Unknown value y 14 | ``` 15 | 16 | ``` 17 | > import Math 18 | 19 | Error found: 20 | in module $PSCI 21 | 22 | Unknown module Math 23 | ``` 24 | 25 | ## Cause 26 | 27 | This error if a name is used but that name is not in scope. Names can refer to various things - values, types, modules, operators, type classes, etc. 28 | 29 | ## Fix 30 | 31 | - Verify the spelling of any names used. 32 | - Verify that the name has been imported. 33 | - If you are using qualified imports, make sure the module name is correct. 34 | - If an import results in an "Unknown module" error, make sure that any required dependencies have been installed. 35 | 36 | ## Notes 37 | -------------------------------------------------------------------------------- /errors/UnnecessaryFFIModule.md: -------------------------------------------------------------------------------- 1 | # `UnnecessaryFFIModule` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnusedDctorExplicitImport.md: -------------------------------------------------------------------------------- 1 | # `UnusedDctorExplicitImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Data.Maybe (Maybe(Just, Nothing)) 9 | 10 | test = Nothing 11 | ``` 12 | 13 | ## Cause 14 | 15 | A module is imported with an explicit imports list including a type with an explicit list of data construtors 16 | (`Maybe(Just,Nothing)` in this example) but some of the mentioned data constructors are unused. 17 | 18 | ## Fix 19 | 20 | Import only the used data constructors: 21 | 22 | ```purescript 23 | import Data.Maybe (Maybe(Nothing)) 24 | ``` 25 | 26 | Alternatively import all data constructors non-explicitly: 27 | 28 | ```purescript 29 | import Data.Maybe (Maybe(..)) 30 | ``` 31 | 32 | ## Notes 33 | 34 | [This error is auto-fixable](../guides/Error-Suggestions.md). 35 | -------------------------------------------------------------------------------- /errors/UnusedDctorImport.md: -------------------------------------------------------------------------------- 1 | # `UnusedDctorImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Data.Maybe (Maybe(..)) 9 | 10 | test :: forall a. Maybe a -> Int 11 | test _ = 42 12 | ``` 13 | 14 | ## Cause 15 | 16 | A module is imported with an explicit imports list including a type with data construtors (`Maybe(..)` in this example) 17 | but only the type constructor and not its data constructors are used. 18 | 19 | ## Fix 20 | 21 | Import only the type without data constructors. In the above example: 22 | 23 | ```purescript 24 | import Data.Maybe (Maybe) 25 | ``` 26 | 27 | ## Notes 28 | 29 | [This error is auto-fixable](../guides/Error-Suggestions.md). 30 | -------------------------------------------------------------------------------- /errors/UnusedExplicitImport.md: -------------------------------------------------------------------------------- 1 | # `UnusedExplicitImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Data.Maybe (maybe, Maybe(..)) 9 | 10 | test = Just -- maybe is not used 11 | ``` 12 | 13 | ## Cause 14 | 15 | A module is imported with an explicit imports list but not all of the identifiers are used. 16 | 17 | ## Fix 18 | 19 | Remove the unnecessary identifiers as suggested. 20 | 21 | ## Notes 22 | 23 | [This error is auto-fixable](../guides/Error-Suggestions.md). -------------------------------------------------------------------------------- /errors/UnusedFFIImplementations.md: -------------------------------------------------------------------------------- 1 | # `UnusedFFIImplementations` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UnusedImport.md: -------------------------------------------------------------------------------- 1 | # `UnusedImport` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | import Some.Module 9 | 10 | -- Nothing from Some.Module is ever used 11 | ``` 12 | 13 | ## Cause 14 | 15 | There is a statement `import Some.Module` which is not required, as nothing from `Some.Module` is used (with the same qualifier if any). 16 | 17 | ## Fix 18 | 19 | Remove the import statement. 20 | 21 | ## Notes 22 | 23 | Often occurs during development when the code using the import has not yet been written, in which case can be ignored. 24 | 25 | [This error is auto-fixable](../guides/Error-Suggestions.md). 26 | -------------------------------------------------------------------------------- /errors/UnusedTypeVar.md: -------------------------------------------------------------------------------- 1 | # `UnusedTypeVar` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/UserDefinedWarning.md: -------------------------------------------------------------------------------- 1 | # `UserDefinedWarning` Error 2 | 3 | ## Example 4 | 5 | ```purescript 6 | module ShortFailingExample where 7 | 8 | ... 9 | ``` 10 | 11 | ## Cause 12 | 13 | Explain why a user might see this error. 14 | 15 | ## Fix 16 | 17 | - Suggest possible solutions. 18 | 19 | ## Notes 20 | 21 | - Additional notes. 22 | -------------------------------------------------------------------------------- /errors/WildcardInferredType.md: -------------------------------------------------------------------------------- 1 | # `WildcardInferredType` Warning 2 | 3 | ## Example 4 | 5 | ```purescript 6 | test :: _ 7 | test = [1, 2, 3] 8 | ``` 9 | 10 | ## Cause 11 | 12 | This warning is shown when you use a _type wildcard_ in your code. In the example above, the type of `test` is given as a wildcard. The warning will show the inferred type of the wildcard as `Array Int`. 13 | 14 | This is an encouragement to document your code by using complete type signatures, but it will not cause any errors. 15 | 16 | ## Fix 17 | 18 | - To remove the warning, replace the type wildcard with the suggested type. Some editor plugins provide the ability to do the replacement automatically. 19 | 20 | ## Notes 21 | -------------------------------------------------------------------------------- /guides/Common-Operators.md: -------------------------------------------------------------------------------- 1 | # Common Operators 2 | 3 | Or, "what is the PureScript equivalent of \ in JS?" 4 | 5 | Although the PureScript language defines no built-in operators, plenty are defined in the `Prelude` and other core libraries. This guide gives you an overview of these operators and the corresponding operators in JavaScript. 6 | 7 | ## JavaScript's unary operators 8 | 9 | All PureScript operators are binary, with one exception: there is syntax sugar for unary negation, whereby in PureScript code, `-x` is desugared to `negate x`, which uses whichever `negate` is in scope. 10 | 11 | This means that the PureScript analogues to unary JavaScript operators (other than `-`) are not operators, but normal functions which must be applied using the standard prefix-style function application, so e.g. `!x` in JS must be written as `not x` in PureScript. 12 | 13 | | JS Operator | PureScript Function | Defined in | Meaning | 14 | |-------------|---------------------|-----------------------|------------------| 15 | | `-` | `negate` | `Data.Ring` | Numeric negation | 16 | | `!` | `not` | `Data.HeytingAlgebra` | Boolean negation | 17 | | `~` | `complement` | `Data.Int.Bits` | Bitwise negation | 18 | 19 | ## JavaScript's binary operators 20 | 21 | | JS Operator | PureScript Function | Defined in | Meaning | 22 | |-------------|---------------------|-----------------------|------------------------------------------| 23 | | `+` | `+` | `Data.Semiring` | Numeric addition | 24 | | `+` | `<>` | `Data.Semigroup` | String concatenation | 25 | | `-` | `-` | `Data.Ring` | Numeric subtraction | 26 | | `*` | `*` | `Data.Semiring` | Numeric multiplication | 27 | | `/` | `/` | `Data.EuclideanRing` | Numeric division | 28 | | `%` | `%` (see note) | `Math` | Remainder, the same as JS' `%` operator. | 29 | | `%` | `mod` (see note) | `Data.EuclideanRing` | Also remainder (see note) | 30 | | `==` | `==` | `Data.Eq` | Equality check | 31 | | `!=` | `/=` | `Data.Eq` | Inequality check | 32 | | `<` | `<` | `Data.Ord` | Less than | 33 | | `<=` | `<=` | `Data.Ord` | Less than or equal | 34 | | `>` | `>` | `Data.Ord` | Greater than | 35 | | `>=` | `>=` | `Data.Ord` | Greater than or equal | 36 | | `&&` | `&&` | `Data.HeytingAlgebra` | Boolean AND | 37 | | `\|\|` | `\|\|` | `Data.HeytingAlgebra` | Boolean OR | 38 | | `&` | `.&.` | `Data.Int.Bits` | Bitwise AND | 39 | | `\|` | `.\|.` | `Data.Int.Bits` | Bitwise OR | 40 | | `^` | `.^.` | `Data.Int.Bits` | Bitwise XOR | 41 | | `<<` | `shl` | `Data.Int.Bits` | Shift Left | 42 | | `>>` | `shr` | `Data.Int.Bits` | Shift Right | 43 | | `>>>` | `zshr` | `Data.Int.Bits` | Zero-fill Shift Right | 44 | 45 | Most of these functions and operators are re-exported by the `Prelude`, so to have access to them in your code, you should normally just write `import Prelude`. 46 | 47 | Additionally, many of these functions and operators are defined in type classes and work with lots of different types. For example, `+` and `*` work with not only `Int` and `Number`, but also any instance of the `Semiring` type class defined in the `Prelude`. 48 | 49 | ### A note on remainder/modulus (`%`) 50 | 51 | Normally, when we ask for the remainder of one number after dividing by another, we are talking about integers. Clearly the remainder of 10 after dividing by 3 is 1, and indeed in JS, `10 % 3 == 1`. Likewise, in PureScript, ``10 `mod` 3 == 1``. 52 | 53 | It's a bit harder to say what a 'remainder' operation should mean if we are trying to extend it to real (non-integral) numbers, though. Real numbers can be divided into one another with nothing 'left over', i.e. in some sense, the remainder of dividing one number by another is always 0. 54 | 55 | Since JS just has one number type, it has to come up with a sensible way of handling cases where one or both of its arguments are non-integral. To address this, it uses a behaviour where it tries to find the largest *integer* multiple of the second argument which is smaller than the first argument, and then returns the difference between these. For example, in JS, `10.5 % 3 == 1.5`. 56 | 57 | If this is the behaviour you want in PureScript, you should use `%` from the `Math` module in `purescript-math`. Its type is `Number -> Number -> Number` and it simply delegates to the `%` operator in JS. 58 | 59 | However, PureScript's `Prelude` aims to provide a stronger theoretical foundation for common operators such as this one, which is why the `Prelude` exports a slightly different function, `mod :: forall a. EuclideanRing a => a -> a -> a`. For integers, `mod` works how you expect it to: ``10 `mod` 3 == 1``, just as before. However, for Numbers, `mod` always returns 0. This may be surprising; however, the reason it works this way is that it is based upon a mathematical structure called a *Euclidean Ring*, whose definition requires this behaviour. For more info, see the [EuclideanRing documentation](https://pursuit.purescript.org/packages/purescript-prelude/4.1.0/docs/Data.EuclideanRing#t:EuclideanRing). 60 | -------------------------------------------------------------------------------- /guides/Contrib-Guidelines.md: -------------------------------------------------------------------------------- 1 | # Contrib Library Guidelines 2 | 3 | `purescript-contrib` is an organization for community-driven libraries. In an effort to avoid bitrotted code, the following guidelines will be enforced on a semi-regular basis: 4 | 5 | - Projects should be **maintained**. Each library should have a clearly-identified maintainer who is responsible for responding to pull requests and issues. To yield maintainership, the maintainer should simply open an issue and we'll find a new maintainer or deprecate the library. 6 | - Projects should be **up to date**. Specifically they should build against the current core library set (up to a reasonable time window), or be identified as deprecated or seeking a new maintainer. 7 | - Projects should be **documented**. Typically, this just involves running `psc-docs` as part of the build process, but `contrib` libraries should also strive to document every exported type and function with some combination of text and examples. 8 | 9 | Contrib libraries should try to follow the [Style Guide](Style-Guide.md) as closely as possible. 10 | 11 | Maintainers who do not follow these guidelines will be asked to move their repositories out of `purescript-contrib`. 12 | -------------------------------------------------------------------------------- /guides/Custom-Type-Errors.md: -------------------------------------------------------------------------------- 1 | See the [24 days of PureScript 2016 post](https://github.com/paf31/24-days-of-purescript-2016/blob/master/21.markdown). 2 | 3 | ## The Warn type class 4 | 5 | There is a type class in `Prim` called `Warn` - which, like `Fail` is indexed by a `Symbol`. 6 | When the compiler solves a `Warn` constraint it will trivially solve the instance and print out the message as a user defined warning. 7 | 8 | ### Deprecation example 9 | 10 | One possible use case for this is custom deprecation warnings. 11 | You start with a library that exports a function `notBad`: 12 | 13 | ```purescript 14 | notBad :: Int 15 | notBad = 21 16 | ``` 17 | 18 | But now you decide there is something `better`; you want to deprecate `notBad` in favour of this new function: 19 | 20 | ```purescript 21 | notBad :: Warn "`notBad` is deprecated. Prefer `better` instead." => Int 22 | notBad = 21 23 | 24 | better :: Int 25 | better = 42 26 | ``` 27 | 28 | Now when someone uses `notBad`, they see the following compiler warning: 29 | 30 | ``` 31 | A custom warning occurred while solving type class constraints: 32 | 33 | `notBad` is deprecated. Prefer `better` instead. 34 | ``` 35 | -------------------------------------------------------------------------------- /guides/Error-Suggestions.md: -------------------------------------------------------------------------------- 1 | # Error/warning suggestions 2 | 3 | Several of the compiler errors/warnings provide a suggestion of how to fix the issue, not only in the textual 4 | ouput of the compiler, but in the JSON output in a machine-usable format. 5 | 6 | ### Supported tools 7 | 8 | * [purescript-suggest](https://github.com/nwolverson/purescript-suggest) - command line tool which can display or apply all suggestions at once 9 | * [pscid](https://github.com/kRITZCREEK/pscid#suggestions) - apply a single suggestion on a keypress 10 | * [psc-ide-emacs](https://github.com/epost/psc-ide-emacs#insert-suggestion-from-error-c-c-m-s) 11 | * [psc-ide-vim](https://github.com/FrigoEU/psc-ide-vim/blob/master/doc/psc-ide-vim.txt#L61) 12 | * [atom-ide-purescript](https://github.com/nwolverson/atom-ide-purescript#error-suggestions--quick-fix) 13 | * [vscode-ide-purescript](https://github.com/nwolverson/vscode-ide-purescript) 14 | 15 | ### Fixable issues 16 | 17 | Classes of issues with support for auto-fix suggestions: 18 | 19 | * Import warnings (e.g. remove unused imports, make import explicit) 20 | * Missing type annotation (top level type annotations and `_`) -------------------------------------------------------------------------------- /guides/FFI-Tips.md: -------------------------------------------------------------------------------- 1 | # PureScript FFI Tips 2 | 3 | ## Use `mkFn` and `runFn` 4 | 5 | All functions in PureScript take exactly one argument, but when writing an interface to an existing JavaScript library often there is a need to expose multiple argument functions. One way to deal with this is to write some inline FFI code that "manually" curries a version of the function you want to bring in to PureScript: 6 | 7 | ```purescript 8 | module Path where 9 | 10 | foreign import joinPath :: FilePath -> FilePath -> FilePath 11 | ``` 12 | 13 | ```javascript 14 | exports.joinPath = function(start) { 15 | return function(end) { 16 | return require('path').join(start, end); 17 | }; 18 | }; 19 | ``` 20 | 21 | This is quite tedious and error prone, so there's an alternative representation of function types, `Fn0` up to `Fn10` available from the module `Data.Function.Uncurried` (from [`purescript-functions`](https://github.com/purescript/purescript-functions)). Making use of these types allows us to greatly simplify the previous example: 22 | 23 | ```purescript 24 | module Path where 25 | 26 | foreign import joinPathImpl :: Fn2 FilePath FilePath FilePath 27 | ``` 28 | 29 | ```javascript 30 | exports.joinPathImpl = require('path').join; 31 | ``` 32 | 33 | However, these `Fn0`..`Fn10` types cannot be applied as normal PureScript functions, they require a corresponding `runFn0`..`runFn10` call to execute. The `runFn` definitions essentially do the work of taking a multi-argument function and returning a curried version for you. 34 | 35 | Taking the previous example again, to avoid having to use `runFn2` every time we want to make use of `joinPath`, the usual way of doing this would be to suffix the foreign import with "Impl" and then define a more PureScript-friendly version that uses `runFn2`: 36 | 37 | ```purescript 38 | foreign import joinPathImpl :: Fn2 FilePath FilePath FilePath 39 | 40 | joinPath :: FilePath -> FilePath -> FilePath 41 | joinPath = runFn2 joinPathImpl 42 | ``` 43 | 44 | The module would then hide the `joinPathImpl` export, only revealing our nice `joinPath` version. 45 | 46 | Special support has been added to the compiler as of PureScript 0.5.4 to inline `runFn` calls when they are fully saturated (that is, applied with all the arguments at once), so it is recommended to avoid point-free style when making definitions that use `runFn`. Taking the above example again: 47 | 48 | ```purescript 49 | joinPath :: FilePath -> FilePath -> FilePath 50 | joinPath start end = runFn2 joinPathImpl start end 51 | ``` 52 | 53 | ## Avoid directly calling PS code from foreign modules 54 | 55 | When implementing things in the FFI, sometimes it's useful to be able to call other functions or make use of data constructors defined in PureScript. For example, if you wanted to write a function that returned a `Maybe` you might do something like this: 56 | 57 | ```purescript 58 | foreign import doSomethingImpl :: forall a. Fn2 (a -> Boolean) a (Maybe a) 59 | 60 | doSomething :: forall a. (a -> Boolean) -> a -> Maybe a 61 | doSomething fn x = runFn2 doSomethingImpl fn x 62 | ``` 63 | 64 | ```javascript 65 | exports.doSomethingImpl = function(fn, x) { 66 | if (fn(x)) { 67 | return Data_Maybe.Just.create(x); 68 | } else { 69 | return Data_Maybe.Nothing.value; 70 | } 71 | }; 72 | ``` 73 | 74 | Calling these functions directly in the FFI code isn't recommended as it makes the code brittle to changes in the code generator. Additionally, doing this can cause problems when using `purs bundle` for dead code elimination. 75 | 76 | The recommended approach is to add extra arguments to your FFI-defined function to accept the functions you need to call as arguments: 77 | 78 | ```purescript 79 | foreign import doSomethingImpl :: forall a. Fn4 (a -> Maybe a) (Maybe a) (a -> Boolean) a (Maybe a) 80 | 81 | doSomething :: forall a. (a -> Boolean) -> a -> Maybe a 82 | doSomething fn x = runFn4 doSomethingImpl Just Nothing fn x 83 | ``` 84 | 85 | ```javascript 86 | exports.doSomethingImpl = function(just, nothing, fn, value) { 87 | if (fn(value)) { 88 | return just(value); 89 | } else { 90 | return nothing; 91 | } 92 | }; 93 | ``` 94 | 95 | This way the compiler knows `Just` and `Nothing` are used so you don't need to worry about dead code elimination removing them, and also you don't have to deal with any future changes that may happen to the way code is generated for data constructors in the generated output. 96 | 97 | This technique also helps when you want to call a function that is a type class member via the FFI. A contrived example using `show`: 98 | 99 | ```purescript 100 | foreign import showSomethingImpl :: forall a. Fn3 (Maybe a -> Boolean) (a -> String) (Maybe a) String 101 | 102 | showSomething :: forall a. (Show a) => Maybe a -> String 103 | showSomething x = runFn3 showSomethingImpl isJust show x 104 | ``` 105 | 106 | ```javascript 107 | exports.doSomethingImpl = function(isJust, show, value) { 108 | if (isJust(value)) { 109 | return "It's something: " + show(value); 110 | } else { 111 | return "It's nothing."; 112 | } 113 | }; 114 | ``` 115 | 116 | By moving the `show` reference out to `showSomething` the compiler will pick the right `Show` instance for us at that point, so we don't have to deal with typeclass dictionaries in `showSomethingImpl`. 117 | 118 | ## Why Doesn't my `Eff` Work When Passed to a Normal JS Function? 119 | 120 | ["Representing Side Effects"](https://leanpub.com/purescript/read#leanpub-auto-representing-side-effects) in *PureScript by Example*. 121 | 122 | In order to avoid prematurely evaluating effects (or evaluating effects that should not be evaluated at all), PureScript wraps them in constant functions: 123 | 124 | ```javascript 125 | exports.myEff = function() { 126 | return doSomethingEffectful(1, 2, 3); 127 | } 128 | ``` 129 | 130 | which is imported to PureScript as: 131 | 132 | ```purescript 133 | foreign import myEff :: forall eff. Eff (myEff :: MYEFF | eff) SomeType 134 | ``` 135 | -------------------------------------------------------------------------------- /guides/FFI.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Foreign Function Interface 3 | author: Phil Freeman 4 | published: 2015-07-15 5 | --- 6 | 7 | In this short post, I'll show how to interoperate with Javascript code using PureScript's Foreign Function Interface (or _FFI_). We'll see how to call Javascript code from PureScript code and vice versa. 8 | 9 | #### Disclaimer 10 | 11 | It should be said that choosing to work with Javascript via the FFI will "void the warranty" of the typechecker to a certain extent. Once you step outside the safe confines of the PureScript type system, nothing is guaranteed, so it is recommended that you know a few basics of the language implementation before writing your own FFI bindings. That said, the correspondence between PureScript types and their Javascript representations is fairly simple, so it should not be too difficult to understand. 12 | 13 | #### Calling PureScript from Javascript 14 | 15 | Calling a PureScript function from Javascript is very simple, at least for functions with simple types. 16 | 17 | Let's take the following simple module as an example: 18 | 19 | ``` haskell 20 | module Test where 21 | 22 | import Prelude 23 | 24 | gcd :: Int -> Int -> Int 25 | gcd n m | n == 0 = m 26 | gcd n m | m == 0 = n 27 | gcd n m | n > m = gcd (n - m) m 28 | gcd n m = gcd (m - n) n 29 | ``` 30 | 31 | This function finds the greatest common divisor of two numbers by repeated subtraction. It is a nice example of a case where you might like to use PureScript to define the function, but have a requirement to call it from Javascript: it is simple to define this function in PureScript since it is made up of pattern matches and recursion, and the implementor can benefit from the use of the type checker. 32 | 33 | To understand how this function can be called from Javascript, it is important to realize that PureScript functions always get turned into Javascript functions _of a single argument_, so we need to apply its arguments one-by-one: 34 | 35 | ``` javascript 36 | var Test = require('Test'); 37 | Test.gcd(15)(20); 38 | ``` 39 | 40 | Here, I am assuming that the code was compiled with `psc`, which compiles PureScript modules to CommonJS modules. For that reason, I was able to reference the `gcd` function on the `Test` object, after importing the `Test` module using `require`. 41 | 42 | You might also like to bundle JavaScript code for the browser, using `purs bundle`. In that case, you would access the `Test` module on the global namespace, which defaults to `PS`: 43 | 44 | ``` javascript 45 | var Test = PS.Test; 46 | Test.gcd(15)(20); 47 | ``` 48 | 49 | #### Understanding Name Generation 50 | 51 | PureScript aims to preserve names during code generation as much as possible. In particular, most identifiers which are neither PureScript nor Javascript keywords can be expected to be preserved, at least for names of top-level declarations. 52 | 53 | If you decide to use a Javascript keyword as an identifier, the name will be escaped with a double dollar symbol. For example, 54 | 55 | ``` haskell 56 | null = [] 57 | ``` 58 | 59 | generates the following Javascript: 60 | 61 | ``` javascript 62 | var $$null = []; 63 | ``` 64 | 65 | In addition, if you would like to use special characters in your identifier names, they will be escaped using a single dollar symbol. For example, 66 | 67 | ``` haskell 68 | example' = 100 69 | ``` 70 | 71 | generates the following Javascript: 72 | 73 | ``` javascript 74 | var example$prime = 100; 75 | ``` 76 | 77 | #### Calling Javascript from PureScript 78 | 79 | Javascript values and functions can be used from PureScript by using the FFI. The problem becomes how to choose suitable types for values originating in Javascript. 80 | 81 | The general rule regarding types is that you can enforce as little or as much type safety as you like when using the FFI, but you should be careful to avoid common pitfalls when dealing with Javascript values, like the possibility of null or undefined values being returned from a Javascript function. Functions defined in the Prelude and core libraries tend to err on the side of type safety where possible. 82 | 83 | #### Foreign Modules 84 | 85 | In PureScript, JavaScript code is wrapped using a _foreign module_. A foreign module is just a CommonJS module which is associated with a PureScript module. Foreign modules are required to adhere to certain conventions: 86 | 87 | - The name of the foreign module must be the same as its companion PureScript module, with its extension changed to `.js`. This associates the foreign module with the PureScript module. 88 | - All exports must be of the form `exports.name = value;`, specified at the top level. 89 | 90 | Here is an example, where we export a function which computes interest amounts from a foreign module: 91 | 92 | ```javascript 93 | "use strict"; 94 | 95 | exports.calculateInterest = function(amount) { 96 | return amount * 0.1; 97 | }; 98 | ``` 99 | 100 | This file should be saved as `src/Interest.js`. The corresponding PureScript module `Interest` will be saved in `src/Interest.purs`, and will look like this: 101 | 102 | ```purescript 103 | module Interest where 104 | 105 | foreign import calculateInterest :: Number -> Number 106 | ``` 107 | 108 | In the companion PureScript module, we simply assign a type to the exports of the foreign module by using a `foreign import` declaration. These values are then available to modules which `import` our PureScript module. 109 | 110 | #### Functions of Multiple Arguments 111 | 112 | PureScript functions are curried by default, so Javascript functions of multiple arguments require special treatment. 113 | 114 | Suppose we wanted to modify our `calculateInterest` function to take a second argument: 115 | 116 | ```javascript 117 | "use strict"; 118 | 119 | exports.calculateInterest = function(amount, months) { 120 | return amount * Math.exp(0.1, months); 121 | }; 122 | ``` 123 | 124 | A correct `foreign import` declaration now should use a foreign type whose runtime representation correctly handles functions of multiple arguments. The `purescript-functions` package provides a collection of such types for function arities from 0 to 10: 125 | 126 | ```purescript 127 | module Interest where 128 | 129 | import Data.Function.Uncurried (Fn2) 130 | 131 | foreign import calculateInterest :: Fn2 Number Number Number 132 | ``` 133 | 134 | Here, the `Fn2` type constructor is used to wrap Javascript functions of two arguments. We can write a curried wrapper function in PureScript which will allow partial application: 135 | 136 | ```purescript 137 | calculateInterestCurried :: Number -> Number -> Number 138 | calculateInterestCurried = runFn2 calculateInterest 139 | ``` 140 | 141 | An alternative is to use curried functions in the native module, using multiple nested functions, each with a single argument, as the runtime representation of the function type constructor `(->)` dictates: 142 | 143 | ```javascript 144 | "use strict"; 145 | 146 | exports.calculateInterest = function(amount) { 147 | return function(months) { 148 | return amount * Math.exp(0.1, months); 149 | }; 150 | }; 151 | ``` 152 | 153 | This time, we can assign the curried function type directly: 154 | 155 | ```purescript 156 | foreign import calculateInterest :: Number -> Number -> Number 157 | ``` 158 | 159 | #### Handling Constrained Types 160 | 161 | Another special case that you should be aware of when calling PureScript functions from Javascript is that values with constrained types (i.e. types which contain type class constraints) contain extra parameters which are used to pass type class dictionaries to the function. 162 | 163 | For example, let's write a simple PureScript function with a constrained type, and look at the generated Javascript. 164 | 165 | ``` haskell 166 | module Test where 167 | 168 | import Prelude 169 | import Data.Tuple (Tuple(..)) 170 | 171 | inOrder :: forall a. Ord a => a -> a -> Tuple a a 172 | inOrder a1 a2 | a1 < a2 = Tuple a1 a2 173 | inOrder a1 a2 = Tuple a2 a1 174 | ``` 175 | 176 | The generated Javascript looks like this: 177 | 178 | ``` javascript 179 | var inOrder = function (__dict_Ord_32) { 180 | return function (_1) { 181 | return function (_2) { 182 | if (Prelude["<"](__dict_Ord_32)(_1)(_2)) { 183 | return Data_Tuple.Tuple(_1)(_2); 184 | }; 185 | return Data_Tuple.Tuple(_2)(_1); 186 | }; 187 | }; 188 | }; 189 | ``` 190 | 191 | Notice that `inOrder` is a (curried) function of three arguments, not two. The first argument is the type class dictionary for the `Ord` constraint. 192 | 193 | We can call this function from Javascript by passing an explicit type class dictionary from the Prelude as the first parameter: 194 | 195 | ``` javascript 196 | var test = Test.inOrder(Prelude.ordNumber())(20)(10); 197 | ``` 198 | 199 | #### Handling Side Effects 200 | 201 | Notice that the `calculateInterest` functions defined above were _pure_: they had no side-effects and produced the same result for the same input on every invocation. 202 | 203 | The PureScript function type `a -> b` does not allow for side-effects, so it would be incorrect to assign a function type to a Javascript computation with side-effects. The correct approach in this case is to use the `Effect` type constructor, defined in the `purescript-effect` package, to assign a type to the computation. 204 | 205 | The `Effect` type constructor and its usage is documented [on Pursuit](https://pursuit.purescript.org/packages/purescript-effect). 206 | 207 | #### Santizing Foreign Data With Data.Foreign 208 | 209 | Data returned from Javascript functions cannot generally be trusted to be defined and non-null. PureScript functions in the Prelude and common libraries generally assume that values will be neither `undefined` nor `null`, so it is important to sanitize data when working with values returned from Javascript functions using the FFI. 210 | 211 | The `Data.Foreign` module (available in the `purescript-foreign` package) defines a `Foreign` data type, and several helper functions for turning `Foreign` values into regular PureScript values, as well as support for handling `null` and `undefined` using the `Maybe` type constructor. 212 | 213 | #### Defining Foreign Data Types 214 | 215 | It is often useful when wrapping Javascript APIs to create new types at a specific kind for use with the FFI. 216 | 217 | For example, suppose we have a Javascript library `frob` which defines the `Frob` data structure and associated functions. To give meaningful types to those functions, it might be useful to define a type `Frob` at kind `Type`. We can do this as follows: 218 | 219 | ``` haskell 220 | foreign import data Frob :: Type 221 | ``` 222 | 223 | The type `Frob` can now be used in other types, or in foreign import declarations: 224 | 225 | ``` haskell 226 | foreign import makeFrob :: String -> Frob 227 | ``` 228 | 229 | Developers who define their own foreign data types should take care to document their expected runtime representations. 230 | 231 | #### Conclusion 232 | 233 | I have hopefully shown that interoperating with Javascript is simple in both directions, once a few small implementation details are understood. You should now be able to wrap your Javascript libraries for use in PureScript, and vice versa. 234 | 235 | The [PureScript book](https://leanpub.com/purescript/read#leanpub-auto-the-foreign-function-interface) contains more information on the FFI, and plenty of examples and exercises for any interested readers. 236 | -------------------------------------------------------------------------------- /guides/Getting-Started.md: -------------------------------------------------------------------------------- 1 | # Getting Started with PureScript 2 | 3 | Let's walk through the basics of getting set up to use the PureScript compiler `purs`, and its interactive mode `purs repl`. 4 | 5 | We'll start with the installation of the compiler and Pulp build tool, and then go through the basic usage of `purs repl`, working towards a solution of problem 1 from [Project Euler](http://projecteuler.net/problem=1). 6 | 7 | #### Installing the Compiler 8 | 9 | You'll need [Node.js and npm](https://docs.npmjs.com/getting-started/installing-node) and to be [able to install global packages](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-1-change-the-permission-to-npm-s-default-directory) to proceed. 10 | 11 | The Purescript compiler (`purs`) can be installed with npm: 12 | 13 | npm install -g purescript 14 | 15 | (It can also be installed from [Hackage](http://hackage.haskell.org/package/purescript), or by downloading the latest [binary bundle](https://github.com/purescript/purescript/releases) for your OS. If you do so, make sure the `purs` executable is on your `$PATH`.) 16 | 17 | #### Setting up the Development Environment 18 | 19 | PureScript's core libraries are configured to use the [Pulp](https://github.com/purescript-contrib/pulp) build tool, and packages are available in the [Bower registry](http://bower.io/search/?q=purescript-). 20 | 21 | If you don't have Pulp and Bower installed, install them now: 22 | 23 | npm install -g pulp bower 24 | 25 | Create a new project in an empty directory using `pulp init`: 26 | 27 | pulp init 28 | 29 | Your directory should now contain the following files: 30 | 31 | - `bower.json` - contains library dependency information 32 | - `bower_components/` - a directory for installed dependencies 33 | - `src/Main.purs` - Entry point module for your project 34 | - `test/Main.purs` - An empty test suite 35 | 36 | At this point, you should be able to build the project and run the tests: 37 | 38 | pulp build 39 | pulp test 40 | 41 | You should see output similar to the following: 42 | 43 | * Building project in /Users/paf31/Documents/Code/purescript/pulp-test 44 | * Build successful. Running tests... 45 | You should add some tests. 46 | * Tests OK. 47 | 48 | If everything was built successfully, and the tests ran without problems, then the last line should state "Tests OK". 49 | 50 | #### Installing Dependencies 51 | 52 | Dependencies can be installed using Bower. We will be using the `purescript-lists` library shortly, so install it now: 53 | 54 | bower install purescript-lists --save 55 | 56 | #### Working in PSCI 57 | 58 | PSCi is the interactive mode of PureScript. It is useful for working with pure computations, and for testing ideas. 59 | 60 | Open PSCi by typing `pulp repl` at the command line. Pulp will create a file in your directory called `.purs-repl`, which contains instructions to PSCi to load your modules and dependencies. If you invoke the PSCi executable directly, you would need to load these files by hand. 61 | 62 | PSCi, version 0.12.0 63 | Type :? for help 64 | 65 | import Prelude 66 | 67 | > 68 | 69 | As the introduction indicates, you can type `:?` to see a list of commands: 70 | 71 | The following commands are available: 72 | 73 | :? Show this help menu 74 | :quit Quit PSCi 75 | :reload Reload all imported modules while discarding bindings 76 | :clear Discard all imported modules and declared bindings 77 | :browse See all functions in 78 | :type Show the type of 79 | :kind Show the kind of 80 | :show import Show all imported modules 81 | :show loaded Show all loaded modules 82 | :paste paste Enter multiple lines, terminated by ^D 83 | :complete Show completions for as if pressing tab 84 | 85 | Further information is available on the PureScript documentation repository: 86 | --> https://github.com/purescript/documentation/blob/master/guides/PSCi.md 87 | 88 | We will use a selection of these commands during this tutorial. 89 | 90 | Start by pressing the Tab key to use the autocompletion feature. You will see a collection of names of functions from the Prelude which are available to use. 91 | 92 | To see the type of one of these values, first import the appropriate module using the `import` command. `pulp init` configures `.purs-repl` to install `Prelude` automatically, so you won't have to do it yourself. 93 | 94 | Next, use the `:type` command, followed by a space, followed by the name of the value: 95 | 96 | > :type map 97 | forall a b f. Functor f => (a -> b) -> f a -> f b 98 | 99 | > import Data.List 100 | > :type zip 101 | forall a b. List a -> List b -> List (Tuple a b) 102 | 103 | We will be using some of the functions from the `Prelude` and `Data.List` modules, so make sure you have imported those by using the `import` keyword: 104 | 105 | import Prelude 106 | import Data.List 107 | 108 | Note that using `Tab` to autocomplete names can be a useful time-saving device in `psci`. 109 | 110 | #### Solving Project Euler #1 111 | 112 | The following problem is taken from [Project Euler](http://projecteuler.net/problem=1): 113 | 114 | > If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 115 | > 116 | > Find the sum of all the multiples of 3 or 5 below 1000. 117 | 118 | We can solve this problem neatly using functions and function composition, directly in the REPL. 119 | 120 | Let's start by listing all of the natural numbers below 1000 as a list. We can do this using the `range` function from `Data.List`: 121 | 122 | > range 0 999 123 | 124 | You should see a list with 1000 elements printed to the command line. 125 | 126 | This value can be given a name: 127 | 128 | > ns = range 0 999 129 | 130 | Now let's filter out all of those elements which do not meet the criterion. We can use the `filter` function from `Data.List`, by providing a predicate function as its first argument: 131 | 132 | > multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns 133 | 134 | You can see the result by evaluating `multiples` if you like, or even check its type: 135 | 136 | > multiples 137 | (0 : 3 : 5 : 6 : ... 138 | > :type multiples 139 | List Int 140 | 141 | Now we need to find the sum of the `multiples` list, to complete the solution. We can use the `sum` function from the `Data.Foldable` module. 142 | 143 | > import Data.Foldable 144 | > sum multiples 145 | 233168 146 | 147 | When you have finished using PSCi, type `:quit` to quit: 148 | 149 | > :quit 150 | See ya! 151 | 152 | #### Compiling a Solution 153 | 154 | Now that we've seen how to use the REPL to reach the answer, let's move our solution into a source file and compile it. 155 | 156 | Create a new text file `src/Euler.purs` and copy the following code: 157 | 158 | ```purescript 159 | module Euler where 160 | 161 | import Prelude 162 | 163 | import Data.List (range, filter) 164 | import Data.Foldable (sum) 165 | 166 | ns = range 0 999 167 | 168 | multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns 169 | 170 | answer = sum multiples 171 | ``` 172 | 173 | It is possible to load this file directly into the REPL and to continue working: 174 | 175 | pulp repl 176 | > import Euler 177 | > answer 178 | 233168 179 | > :quit 180 | See ya! 181 | 182 | Alternatively, we can use Pulp to compile our new module to JavaScript: 183 | 184 | pulp build 185 | 186 | This will compile each module present in `src/` into a separate file in the `output/` directory. 187 | 188 | The compiler will display several warnings about missing type declarations. In general it is considered good practice to provide explicit type signatures. In this guide, they are left out for brevity. In the absence of type signatures, the PureScript compiler infers types automatically but will remind us to consider adding them. 189 | 190 | #### Writing a Test Suite 191 | 192 | To test our code, we'll use the `purescript-assert` library: 193 | 194 | bower i purescript-assert --save 195 | 196 | Modify the `test/Main.purs` file, and add the following code: 197 | 198 | ```purescript 199 | module Test.Main where 200 | 201 | import Prelude 202 | 203 | import Euler (answer) 204 | import Test.Assert (assert) 205 | 206 | main = do 207 | assert (answer == 233168) 208 | ``` 209 | 210 | Our "test suite" is just a single assertion that the `answer` value equals the correct integer. In a real test suite, we might use the `Effect` monad to compose multiple tests in our `main` function. 211 | 212 | Run the tests using `pulp test`, and you should hopefully see "Tests OK" in the last line. 213 | 214 | #### Creating Executables 215 | 216 | We can modify the `main` function in the `src/Main.purs` module to print our result to the console: 217 | 218 | ```purescript 219 | module Main where 220 | 221 | import Prelude 222 | 223 | import Euler (answer) 224 | import Effect.Console (log) 225 | 226 | main = do 227 | log ("The answer is " <> show answer) 228 | ``` 229 | 230 | The `pulp run` command can be used to compile and run the `Main` module: 231 | 232 | > pulp run 233 | * Building project in pulp-test 234 | * Build successful. 235 | The answer is 233168 236 | 237 | #### What Next? 238 | 239 | If you're new to typed functional programming, your next stop should be [PureScript by Example](https://leanpub.com/purescript/read), which will walk you through learning PureScript by solving practical problems. (Note: At the time of writing, _Purescript by Example_ is compatible with the 0.11.x version of the compiler) 240 | 241 | If you are already familiar with an ML-family language, like Haskell or Elm, PureScript by Example should still be appropriate as a starting point, but you may alternatively want to start by browsing the [language reference in the documentation repository](https://github.com/purescript/documentation/tree/master/language) instead. The language reference gives a more brief, reference-style description of the language, and is aimed at those who are already somewhat familiar with typed functional programming. There is also a [Differences from Haskell](https://github.com/purescript/documentation/blob/master/language/Differences-from-Haskell.md) page which Haskell programmers will find useful. 242 | 243 | New PureScript programmers are also encouraged to spend some time browsing [Pursuit](https://pursuit.purescript.org), which hosts generated API documentation for PureScript libraries. In particular it is worth familiarising yourself with the [core libraries](https://github.com/purescript) (i.e., those which are hosted under the `purescript` organisation on GitHub), and especially the [prelude](https://pursuit.purescript.org/packages/purescript-prelude), as these provide many basic concepts which are frequently useful for writing programs. 244 | -------------------------------------------------------------------------------- /guides/PSCi.md: -------------------------------------------------------------------------------- 1 | PSCi "PureScript Interactive" is the REPL for PureScript. It is often a good way to explore your code, do some basic testing, or to get a feel for a new library. 2 | 3 | ## Getting Started 4 | 5 | Use Pulp to configure and start PSCi: 6 | 7 | ```text 8 | $ npm install -g pulp # Install pulp 9 | 10 | $ cd my-project # Enter an empty folder 11 | 12 | $ pulp init # Initialize a pulp environment 13 | 14 | $ pulp repl # Fire up the interpreter psci 15 | 16 | PSCi, version 0.9.1 17 | Type :? for help 18 | 19 | > "hello" 20 | "hello" 21 | 22 | > import Prelude 23 | 24 | > 1 + 2 * 3 25 | 7 26 | 27 | > import Control.Monad.Eff.Console 28 | 29 | > log "print this to the screen" 30 | print this to the screen 31 | unit 32 | ``` 33 | 34 | For more information about getting started with a development environment, see [this guide](http://www.purescript.org/learn/getting-started/). 35 | 36 | ## Basic usage 37 | 38 | Type expressions into the REPL to have them evaluated: 39 | 40 | > 3 + 4 41 | 7 42 | 43 | Introduce bindings with `=`: 44 | 45 | > x = 4 46 | > x + 9 47 | 13 48 | 49 | You can also define data types, type classes, and type class instances (you may need to use multi-line mode for this): 50 | 51 | > data Season = Spring | Summer | Autumn | Winter 52 | > class Shout a where shout :: a -> a 53 | > instance shoutString :: Shout String where shout s = s <> "!" 54 | 55 | ## Paste mode (previously `--multi-line-mode`) 56 | 57 | Enter `:paste` (or `:p`) to enter multi-line (or "paste") mode. Terminate it with `Control-D` key. 58 | 59 | ``` 60 | > import Prelude 61 | > :paste 62 | … add :: Int -> Int -> Int 63 | … add = \x y -> x + y 64 | > add 10 20 65 | > (^D) 66 | 30 67 | ``` 68 | 69 | [Demo](https://asciinema.org/a/0y56unmja6fqire01x20zb5xx) 70 | 71 | ## `purescript-psci-support` 72 | 73 | ```text 74 | $ psci 75 | 76 | PSCi requires the purescript-psci-support package to be installed. 77 | You can install it using Bower as follows: 78 | 79 | bower i purescript-psci-support --save-dev 80 | 81 | For help getting started, visit http://wiki.purescript.org/PSCi 82 | ``` 83 | 84 | The PureScript compiler suite (i.e. the executable `purs`), unlike most compilers, does not ship with a standard library. In PureScript, even `Prelude` is a normal module, just like any other. Consequentially, `psci` requires a specific library to be installed in order to be able to evaluate terms in the REPL. 85 | 86 | `purescript-psci-support` defines the `Eval` type class for this purpose. Instances of `Eval` are provided for `Show`able types, and for `Eff`, so that we can evaluate actions in the REPL. Library implementors might like to provide `Eval` instances for their own `Eff`-like types. 87 | 88 | ## PSCi Without Pulp 89 | 90 | PSCi can be run directly, by specifying a list of PureScript source files as globs: 91 | 92 | psci 'src/**/*.purs' 'bower_components/purescript-*/src/**/*.purs' 93 | 94 | Note the single quotes—the purescript compiler itself knows how to expand globs (`*`) and recursive globs (`**`), single quotes prevent your shell from expanding them. (Bash for example doesn’t have recursive globbing enabled by default; don’t forget the single quotes.) 95 | -------------------------------------------------------------------------------- /guides/PureScript-Without-Node.md: -------------------------------------------------------------------------------- 1 | The PureScript community has standardized on the NodeJS toolset to a certain extent: we use tools like Pulp, Browserify and Gulp, which run on NodeJS and are installed with NPM, and we use Bower for our package management. However, we have some users who would rather not, or cannot, run NodeJS on their machines. In this short post, I'll demonstrate how to use the PureScript compiler directly on the command line, and how to automate some processes using standard tooling. 2 | 3 | #### Creating a Project 4 | 5 | Create a directory for your project, with `src` and `test` directories for source files and test files: 6 | 7 | ```text 8 | $ mkdir purescript-without-node 9 | $ cd purescript-without-node 10 | $ mkdir src/ test/ 11 | ``` 12 | 13 | Create a file `src/Main.purs` as follows: 14 | 15 | ```purescript 16 | module Main where 17 | 18 | import Effect (Effect) 19 | import Effect.Console (log) 20 | import Data.Unit (Unit) 21 | 22 | main :: Effect Unit 23 | main = log "Hello, World!" 24 | ``` 25 | 26 | #### Installing Dependencies 27 | 28 | Instead of using Bower, we'll need to install dependencies manually. Let's fetch source packages using `git`. For this demo, I'll need `purescript-console`, which has dependencies on `purescript-effect` and `purescript-prelude`: 29 | 30 | ```text 31 | $ mkdir dependencies/ 32 | $ git clone --branch v4.1.0 git@github.com:purescript/purescript-prelude.git dependencies/purescript-prelude/ 33 | $ git clone --branch v2.0.0 git@github.com:purescript/purescript-effect.git dependencies/purescript-effect/ 34 | $ git clone --branch v4.1.0 git@github.com:purescript/purescript-console.git dependencies/purescript-console/ 35 | ``` 36 | 37 | Note that, without Bower as our dependency manager, it's necessary to install all dependencies manually, including transitive dependencies. It's also necessary to manage versions by hand. 38 | 39 | #### Building Sources 40 | 41 | Now we can build our project. It is necessary to provide all source files explicitly to `purs compile`. The simplest way is to use a set of globs: 42 | 43 | ```text 44 | $ purs compile src/Main.purs 'dependencies/purescript-*/src/**/*.purs' 45 | ``` 46 | 47 | Note: FFI files are automatically discovered when a PureScript file uses `foreign import` and are not required in the globs. 48 | 49 | If everything worked, you should see a collection of lines like this 50 | 51 | ```text 52 | Compiling Effect 53 | Compiling Effect.Class 54 | Compiling Effect.Console 55 | ... 56 | ``` 57 | 58 | `purs` will write a collection of CommonJS modules to the output directory. You can use these CommonJS modules in NodeJS, but it is more likely that you will want to bundle them for use in the browser. 59 | 60 | #### Bundling JavaScript for the Browser 61 | 62 | To bundle the generated Javascript code, we will use `purs bundle`. 63 | 64 | `purs bundle` takes a collection of CommonJS module files as input, and generates a single JavaScript file. 65 | 66 | Run `purs bundle` with the following arguments: 67 | 68 | ```text 69 | $ purs bundle output/*/{index,foreign}.js --module Main --main Main 70 | ``` 71 | 72 | The `--module` argument specifies an _entry-point_ module, which will be used to determine dead code which can be removed. For our purposes, we only care about bundling the CommonJS module corresponding to the Main PureScript module and its transitive dependencies. 73 | 74 | The `--main` argument will make the output JavaScript file an executable by adding a line of JavaScript to it which runs the `main` function in the specified module. 75 | 76 | If everything worked, you should see about 100 lines of JavaScript printed out. This can optionally be redirected to a file with the `--output`/`-o` argument. 77 | 78 | You should be able to execute the generated JavaScript using NodeJS. If your PureScript code uses FFI files which `require` NPM modules, you'll need to use a JavaScript bundler, like Webpack or Browserify, before running it in the browser. 79 | 80 | #### Conclusion 81 | 82 | I've shown how it's possible to get started with PureScript without using the tools from the NodeJS ecosystem. Obviously, for larger projects, it takes some work to manage library dependencies this way, which is why the PureScript community has decided to reuse existing tools. However, if you need to avoid those tools for any reason, it is possible to script some standard tasks without them. 83 | -------------------------------------------------------------------------------- /guides/Style-Guide.md: -------------------------------------------------------------------------------- 1 | This page contains guidelines for writing PureScript libraries. You might consider this a set of best practices, or if you would like to contribute to the core libraries, a set of guidelines for getting your pull requests accepted. 2 | 3 | The PureScript core libraries are good examples of how to put these guidelines into practice. 4 | 5 | ## Build Tools 6 | 7 | - Consider using a one-step build tool such as Pulp or `gulp-purescript` to make your build as simple as possible for end-users. 8 | - Document build steps for compilation, testing and documentation clearly in your `README` file. 9 | 10 | ## Documentation 11 | 12 | - Try to document every exported type and function. 13 | - Even if a function seems "self-explanatory", it is still better to include a small comment or example to help beginners. 14 | - Short examples go a long way. Try to distill the essence of your function or type into a few lines and include it in your documentation as a Markdown code block. 15 | 16 | It was previously common to include Markdown documentation generated by `psc-docs` in the repository. However, now that we have [Pursuit](http://pursuit.purescript.org), there is no need to do this. The recommended approach is to link to your documentation on Pursuit from your README, and to avoid checking in Markdown documentation generated by `psc-docs`. 17 | 18 | ## Tests 19 | 20 | - Include tests with your project, so that contributors can easily verify their changes. 21 | - PureScript has several excellent testing libraries, some of which include: 22 | 23 | * Spec: 24 | * Test-Unit: 25 | 26 | ## Examples 27 | 28 | - Write at least one example, which might be a part of your test suite, to document how your library might be used to solve some simple complete use-case. 29 | - Link clearly to an example from your `README` file. 30 | - Make it obvious how to run your example. 31 | - If your example produces output, consider including the output (either as a code comment or in the `README`) 32 | 33 | ## Continuous Integration 34 | 35 | - Set up continuous integration for your project to verify that your library compiles correctly. 36 | - Travis can be set up easily. Here is a template `.travis.yml` file: 37 | 38 | ``` 39 | language: node_js 40 | dist: trusty 41 | sudo: required 42 | node_js: 6 43 | install: 44 | - npm install purescript pulp bower -g 45 | - bower install 46 | script: 47 | - pulp build && pulp test 48 | ``` 49 | 50 | - Display the Travis badge in your `README` file so that the build status is visible. 51 | 52 | ## Publishing 53 | 54 | - Share your library on [Bower](http://bower.io/search/?q=purescript), prefixing the name of your library with `purescript-` so others can find your work. 55 | - Bower works with git tags, but does not require any present tags to publish. Please run `bower version 0.0.0` and push tags for your initial release (this prevents interim work not intended for publication from leaking on `0.0.0` libs). 56 | - Considering that you may need to be editing your library live as a part of the development of your main project, check out `bower link` (learn all about it [here](https://oncletom.io/2013/live-development-bower-component/)). This will enable you to keep the repos in sync as you work, and facilitate publishing when ready. 57 | - `bower link` can also be useful if you plan on contributing to a package needed by your project. Simply fork the repo, and link. Once you have your additional bindings, or features needed for your project working, you can contribute them back to the source repo easily with a Pull Request. 58 | - Share your library on [Pursuit](http://pursuit.purescript.org), so that developers can search your library documentation. 59 | - Include the `Pursuit` version badge in your `README` file, with a link to your documentation on Pursuit. 60 | 61 | ## Types 62 | 63 | - Include type signatures for top-level declarations. Use type wildcards to infer the type if necessary. 64 | - Use `newtype` to convey additional information about primitive types where applicable (for example, consider using `newtype EmailAddress` instead of just `String`). 65 | - Do not misuse the type system when providing bindings via the FFI. Common abuses include `forall props. { | props }` (for "arbitrary records") and `forall a. a -> ...` (to avoid specifying exact types). PureScript has a rich set of types such as `Foreign` and `FnX` for safe interop with JavaScript, so this is never necessary. Create a new foreign data type if need be. 66 | 67 | ## Modules 68 | 69 | - PureScript follows Haskell conventions for module namespacing. Some common top-level namespaces are: 70 | - `Data` for data structures and their functions 71 | - `Control` for control structures 72 | - `Node` for NodeJS-related functionality 73 | - Include a module export list in your modules. 74 | - Strive to keep module exports minimal. 75 | 76 | ## Foreign Function Interface 77 | 78 | - PureScript is a new language, and has a need for high quality FFI libraries. 79 | - If you have already written a library that has FFI code into a native API, consider splitting it into two libraries, a barebones set of FFI bindings, and your extra functionality. 80 | 81 | ## Runtime Requirements 82 | 83 | - NodeJS and the web browser have differences. Note any assumptions about the execution environment (Node-only, browser-only, etc.) in your `README` file. 84 | - Your FFI libraries may come with runtime dependencies (a particular library, for example). Document these clearly, along with any installation steps. 85 | 86 | ## Keeping your library up to date 87 | 88 | - Try to keep your library up to date. 89 | - Consider using [VersionEye](https://www.versioneye.com/). VersionEye reads your `bower.json` file and alerts you if your dependencies go out of date. If you have Travis up and running for CI, you can then easily test to see if those changes are breaking changes, and address them more promptly. 90 | - If your library has been deprecated, document that fact clearly in the `README` file. 91 | -------------------------------------------------------------------------------- /guides/The-Partial-type-class.md: -------------------------------------------------------------------------------- 1 | # This guide has moved to the [purescript-partial library][partial] 2 | 3 | [partial]: https://pursuit.purescript.org/packages/purescript-partial 4 | -------------------------------------------------------------------------------- /guides/psc-ide-FAQ.md: -------------------------------------------------------------------------------- 1 | # Frequently asked `psc-ide` questions 2 | 3 | ## Q: Where can I get psc-ide? 4 | A: From compiler version > 0.8.3 onwards psc-ide is distributed with the compiler and will be installed with the compiler binaries. 5 | 6 | ## Q: How do I get psc-ide support for my editor? 7 | A: If you are using one of Atom, Emacs, VIM or VS Code: 8 | 9 | - Atom: 10 | 11 | 1. install the `language-purescript` package 12 | 2. install the `ide-purescript` package 13 | 14 | - Emacs: 15 | 16 | install `psc-ide` from MELPA 17 | 18 | - (Spacemacs): 19 | 20 | enable the purescript layer 21 | 22 | - VIM: 23 | 24 | `NeoBundle "frigoeu/psc-ide-vim"` 25 | 26 | - VS Code: 27 | 28 | install the ide-purescript package 29 | 30 | For any other editor... you'll have to write your own plugin :smile: 31 | 32 | ## Q: Where can I get documentation for psc-ide? 33 | A: https://github.com/purescript/purescript/tree/master/psc-ide 34 | 35 | ## Q: How can I apply suggestions from PureScript automatically? 36 | A: Try https://github.com/nwolverson/purescript-suggest 37 | 38 | # Troubleshooting 39 | 40 | ## Parsing the externs failed... 41 | 42 | Step 1: Delete your `output/` folder and recompile your project 43 | 44 | Step 2: Check if your `psc --version` and `psc-ide-server --version` match 45 | 46 | Step 3: Check if you have an old psc-ide lying around (think stack, npm or cabal) 47 | 48 | Step 4: Hop onto IRC and start a debugging session with @kritzcreek 49 | -------------------------------------------------------------------------------- /historical/0.10-Migration-Guide.md: -------------------------------------------------------------------------------- 1 | The 0.10 release contains many changes, some of which result in compile errors on PureScript code which previously successfully compiled. 2 | 3 | Because the [v0.10.1 release notes](https://github.com/purescript/purescript/releases/tag/v0.10.1) lists all changes, this page is intended to document how to migrate a project into this new release. 4 | 5 | ## Functional Dependencies 6 | 7 | The type class solver now supports functional dependencies. This affects your project if it uses type classes which use this new feature. Many commonly-used type classes have been updated to use this new feature, which means you should follow the "Library Updated" migration pattern. If your code makes an instance a type class which has been updated to use a functional dependency, your instance may fail type-checking. 8 | 9 | ## Migration Patterns 10 | 11 | 1) Library Updated 12 | If your project contains code which uses a new feature, your project will not compile unless using a new version of the PureScript compiler. Keep in mind that your project's code consists of your own code as well as all libraries it depends on, which means you must use the highest version of the compiler required by you or your libraries. For example, if a library version you're using requires, for example, compiler v2 while your project was planning to use v1, you must now use v2 to compile your project. Alternatively, identify the libraries you use which use v2 compiler features and find earlier versions of them which don't use v2 features. 13 | -------------------------------------------------------------------------------- /historical/Pre-0.5-changelog.md: -------------------------------------------------------------------------------- 1 | ## 0.4.0 Changes 2 | 3 | This release focussed mainly on bug fixes and minor enhancements, in order to provide a stable release of the compiler. 4 | 5 | This release saw major contributions from [a number of new contributors](https://github.com/purescript/purescript/graphs/contributors). Thank you very much to everyone who submitted pull requests, issues and suggestions, and also to the users of the #purescript FreeNode channel for their valuable feedback. As always, new contributors are always welcome! 6 | 7 | - The full language guide can be found [here](http://purescript.readthedocs.org). 8 | - Try out the latest features [here](http://tryps.functorial.com). 9 | 10 | ## Breaking Changes 11 | 12 | - Multiple argument functions are no longer available. 13 | - When used in the browser, PureScript modules are now accessed through `window.PS.`. The `PS` object name can be changed via the `--browser-namespace` compiler argument. 14 | - The `--run-main` argument has been replaced with `--main` which can now accept a module name in which to find the `main` function. 15 | 16 | ### New Features 17 | 18 | - Dead code elimination. The new compiler argument `--module=` can be used to specify one or more modules that should be kept in the generated code along with their dependencies. If no modules are specified, all code is exported. 19 | 20 | ### Enhancements 21 | 22 | - The `->` and `[]` types are now usable in type class instances. 23 | - The file path is included in syntax error messages. 24 | - Most reserved Javascript names (`return`, `const`, etc) are now usable. 25 | - Generated code for operators is more user friendly (for example, `Prelude[">>="]`). Where this transformation cannot be applied, human-readable variable names (e.g. `$greater$greater$eq`) are generated. 26 | - The typechecker's function application judgement was greatly simplified, and as a result, more valid things now typecheck. 27 | - Data constructors with multiple arguments can now be defined. 28 | - It is no longer necessary to sort modules in order of dependencies manually. 29 | - Case statements matching data constructors no longer generate unnecessary constructor checks at runtime if there is only a single data constructor. 30 | - New optimizer rules were added to inline JavaScript's built-in operators. 31 | 32 | ### Bug Fixes 33 | 34 | - Floats parse correctly. 35 | - Using data constructors in pattern matches now works properly across modules. 36 | - PureScript modules no longer overwrite global objects with the same name. 37 | - Show problems with shadowing of names were fixed. 38 | - Problems with recursive non-function values were fixed. 39 | - Type synonyms can now expand to types containing more type synonyms. 40 | - A bug in capture-avoiding type variable substitution which was affecting the `Functor (Either e)` instance was fixed. 41 | - Type synonym instances are now disallowed. 42 | - Precedence rules for some basic operators were corrected. 43 | - A bug which allowed skolem variables to escape their scope was add (thanks to Brian McKenna). 44 | - Modules containing mutually recursive type synonyms and data declarations now compile correctly. 45 | - A number of bugs in the optimizer were addressed. 46 | 47 | ### Libraries 48 | 49 | - The `Prelude` has been greatly expanded. Definitions for built-in JavaScript operators have been moved into the Prelude. 50 | - Gary Burgess has released the [grunt-purescript library](https://github.com/purescript/grunt-purescript) to build PureScript code using Grunt. 51 | - The [purescript-parsing](https://github.com/purescript/purescript-parsing) library provides Parsec-like parsing combinators. 52 | - The [purescript-promises](https://github.com/purescript/purescript-promises) library provides `Monad` and `Applicative` instances for promises. 53 | - The [purescript-quickcheck](https://github.com/purescript/purescript-quickcheck) library provides a very basic implementation of a QuickCheck-style testing harness. 54 | - The [purescript-json](https://github.com/purescript/purescript-json) library aims to provide a safe way to consume JSON data. 55 | 56 | ### Documentation 57 | 58 | - Documentation for the `Prelude` modules is now automatically generated and can be found [here](http://purescript.readthedocs.org/en/latest/prelude.html). 59 | - There is now Hackage documentation. 60 | - Code comments have been improved. 61 | 62 | --- 63 | 64 | ## 0.3.0 Changes 65 | 66 | Many thanks to the [contributors](https://github.com/purescript/purescript/graphs/contributors) who helped with this release. 67 | 68 | - Full language guide can be found [here](http://functorial.com/purescript). 69 | - Try out the latest features [here](http://tryps.functorial.com). 70 | 71 | ## New Features / Enhancements 72 | 73 | - Mutually recursive functions and types are now allowed within a module. 74 | - Syntactic sugar for patterns in top-level declarations has been added. For example: 75 | 76 | sum [] = 0 77 | sum (x:xs) = x + sum xs 78 | 79 | - Basic support for type classes has been added. Polymorphic types of the form `forall a. (C a) => ...` will not be inferred but can be checked. Type inference still works if all type class instances can be determined. There is not yet support for functionality like GHC's `FlexibleInstances`, `FlexibleContexts` or `MultiParamTypesClasses`. For example: 80 | 81 | class Truthy a where 82 | isTrue :: a -> Boolean 83 | 84 | instance Truthy Boolean where 85 | isTrue b = b 86 | 87 | instance Truthy String where 88 | isTrue "" = false 89 | isTrue _ = true 90 | 91 | ifThenElse :: forall a b. (Truthy a) => a -> b -> b -> b 92 | ifThenElse a tr fa = if isTrue a then tr else fa 93 | 94 | - There is now support for `do` notation, using the `Monad` type class from the `Prelude` module. For example: 95 | 96 | data Maybe = Nothing | Just a 97 | 98 | instance Prelude.Monad Maybe where 99 | ret = Just 100 | (>>=) Nothing _ = Nothing 101 | (>>=) (Just a) f = f a 102 | 103 | test = do 104 | x <- Just 1 105 | y <- Just 2 106 | ret $ x + y 107 | 108 | - There is now a better story for side-effects. The `Eff` module in the `Prelude` defines a monad `Eff e` where e is a row of effect types. The kind system now defines a new kind `!` of effects. Row polymorphism allows different native effects to be interleaved. For example: 109 | 110 | test = do 111 | trace "Testing" 112 | throwError "Error!" 113 | 114 | has inferred type `forall eff. Eff (trace :: Trace | error :: Error String | eff)`. 115 | See the `/examples/passing/Eff.purs` file for a more in-depth set of examples. 116 | Supported native effects currently include `ST`, `Trace`, `Error` and `DOM` (via the `libraries/jquery` module). 117 | - There is a new flag `--run-main` which will check the type of the `Main.main` function and emit the call to `main();` after all other generated Javascript. 118 | - The `Prelude` module is now automatically included, unless the `--no-prelude` flag is specified. 119 | - The class of accepted operator names has been expanded. Specifically, `$` is now a valid operator, and is defined in the `Prelude` module. 120 | - Tail calls can be eliminated using the `--tco` flag. 121 | - There is basic support for checking the types of values at runtime, using the `--runtime-type-checks` flag. Right now, this only works for primitive types, and so is a work-in-progress. 122 | - GHCJS/Fay-style foreign imports are now supported. An example is 123 | 124 | foreign import "function(n) { \ 125 | \ return function(p) {\ 126 | \ return Math.pow(n, p);\ 127 | \ }\ 128 | \ }" pow :: Number -> Number -> Number 129 | - Data constructors now get imported along with their type definitions. 130 | - The `-s` flag will now cause the compiler to use `stdin` for input. 131 | - There is a new executable `psci` which provides simple REPL-like functionality - it parses expressions, passes the generated Javascript to Node for execution, and prints the result. This is a work-in-progress. 132 | - The JQuery example (`libraries/jquery/test`) has been improved to use the new `Eff` monad and `do` notation. 133 | 134 | ## Regressions 135 | 136 | - `foreach` is no longer supported. The `Prelude` module defines `map` which should provide the same functionality. 137 | - Support for naked expressions as statements has been removed. 138 | 139 | ## Bug Fixes 140 | 141 | - Operator precedence rules now work across modules. 142 | - A bug in which expressions involving non-qualified names did not typecheck was fixed. 143 | - Trailing spaces have been removed in the generated Javascript, thanks to @utkarshkukreti. 144 | - Type synonyms now work properly across modules. 145 | - Module imports are not transitive, which was previously leading to some unexpected error messages. 146 | - A bug which caused the optimizer to break generated Javascript for mutually recursive values was fixed. 147 | - Some `Prelude` functions which called methods in the standard Javascript library have been fixed. 148 | 149 | --- 150 | 151 | ## 0.2.0 Changes 152 | 153 | Many thanks to the [contributors](https://github.com/purescript/purescript/graphs/contributors) who helped with this release. 154 | 155 | - Full language guide can be found [here](http://functorial.com/purescript). 156 | - Try out the latest features [here](http://tryps.functorial.com). 157 | 158 | ### New Features 159 | 160 | - RankNTypes 161 | 162 | This experimental feature allows polymorphic types (introduced with `forall`) to appear on the left of a function arrow, or as the type of a record field, etc. For example: 163 | 164 | rank2 :: (forall a. a -> a) -> Number 165 | rank2 = \f -> if f true then f 1 else f 2 166 | 167 | - Modules 168 | - Polymorphic Object Update 169 | 170 | Records now support member update in which the type of the field changes during the update. For example: 171 | 172 | data Wrap a = Wrap a 173 | 174 | update = \o -> o { prop = Wrap o.prop } 175 | 176 | ### Enhancements 177 | 178 | - Naked expressions as statements 179 | 180 | Naked expressions of type `{}` can now be used as statements. 181 | 182 | - Split code generation into `AST -> JS` and `JS -> String` 183 | 184 | JavaScript generation is now split into the generation of a JavaScript AST, and the pretty-printing of that AST. This enables some optimizations, and a better JavaScript pretty-printer. 185 | 186 | - Syntactic sugar for introducing curried functions 187 | 188 | Single-argument functions and multiple-argument functions can now be introduced in the same way: 189 | 190 | test = \a (b, c) d -> a + b + c + d 191 | 192 | - JavaScript optimizations 193 | 194 | Some basic dead-variable elimination, inlining and eta-conversion are now performed on the generated JavaScript. 195 | 196 | - Generate formatted Javascript 197 | 198 | The generated JavaScript is now formatted to be more readable. In particular, newlines get generated, and the correct indentation is used. 199 | 200 | - More valid infix operators 201 | 202 | The colon and period characters are now valid in infix operator names. 203 | 204 | ### Syntax Changes 205 | 206 | - Avoid 'do' keyword for blocks 207 | 208 | `do` will be used later for Haskell-like monad comprehensions, so its previous use in introducing blocks of statements is now invalid. The `do` keyword is still reserved. 209 | 210 | - Member foreign import syntax 211 | 212 | A small syntactic addition to the FFI, to support a common use case. 213 | 214 | - Make FFI syntax match Haskell 215 | 216 | Use `foreign import` instead of `extern`. 217 | 218 | - Make record declaration syntax match Haskell 219 | - Simplify array binders 220 | 221 | There are now two types of array binders: cons binders `x : xs -> ...` and array binders `[x, y, z] -> ...` instead of the previously confusing `[x:xs]`. 222 | 223 | - Array indexing syntax is ambiguous 224 | 225 | Array elements are now accessed using the `!!` operator: `arr !! 0` etc. 226 | 227 | ### Bug Fixes 228 | 229 | - Allow guards access to current scope 230 | 231 | ### Libraries 232 | 233 | - Prelude 234 | 235 | There is now a basic prelude in the `libraries/prelude` folder. 236 | -------------------------------------------------------------------------------- /language/FFI.md: -------------------------------------------------------------------------------- 1 | 4 | 外部関数インタフェース(FFI)は、JavaScriptまたはバックエンドで使っている他の言語で書かれたコードとの共存を実現します。 5 | 6 | 10 | 値のインポート 11 | ------------ 12 | 13 | 16 | `foreign import`キーワードはJavaScriptで定義された値や型を宣言します: 17 | 18 | ```purescript 19 | -- src/Math.purs 20 | module Math where 21 | foreign import pow :: Number -> Number -> Number 22 | ``` 23 | 24 | 27 | 値をFFIからインポートするとき、値は分離されたファイルに定義されています。そのファイル名とPureScriptのソースファイル名は、拡張子「.purs」がバックエンドの言語の拡張子に置き換わっている部分を除いて同じであるべきです。例えば、上のコードは`src/Math.purs`に書かれており、対応するFFIファイルは`src/Math.js`です。以下のようになるかもしれません: 28 | 29 | ```javascript 30 | // src/Math.js 31 | "use strict"; 32 | exports.pow = function(x) { 33 | return function(y) { 34 | return Math.pow(x,y); 35 | }; 36 | }; 37 | ``` 38 | 39 | 42 | コンパイラは、PureScriptファイルが`foreign import`を通じてインポートした値がFFIファイルで公開されていることを確かめます。しかし、コンパイラはFFIファイルで定義された値の実行時表現に正しい型を与えているかどうかまでは確かめられないので、その責務はあなた自身にあります。インポートした値を`Int`として宣言したなら、その値が真に`Int`であるようにしてください(配列や関数などではなく)。 43 | 44 | 48 | 型のインポート 49 | ------------ 50 | 51 | 54 | 新しい抽象型(コンストラクタがないもの)を宣言するためには、`foreign import data`を使って種を与えます: 55 | 56 | ```purescript 57 | foreign import data DOMElement :: Type 58 | 59 | foreign import document :: { 60 | createElement :: String -> DOMElement 61 | } 62 | ``` 63 | 64 | 67 | この方法で型を宣言しているときは、単に`Type`ではなく、何らかの種を持つように型を宣言するかもしれません。例えば、副作用の種を宣言するには次のようにします: 68 | 69 | ```purescript 70 | foreign import data MyRow :: # Effect 71 | ``` 72 | -------------------------------------------------------------------------------- /language/Modules.md: -------------------------------------------------------------------------------- 1 | 4 | # モジュール 5 | 6 | 9 | PureScriptの全てのコードはモジュールに含まれます。モジュールは`module`キーワードによって導入されます: 10 | 11 | ```purescript 12 | module A where 13 | 14 | id x = x 15 | ``` 16 | 17 | 20 | ## モジュールの読み込み 21 | 22 | 25 | モジュールは`import`キーワードを使うことで読み込まれます。これは「openインポート」と呼ばれ、モジュール内の全ての値や型の別名を作成します: 26 | 27 | ```purescript 28 | module B where 29 | 30 | import A 31 | ``` 32 | 33 | 36 | 代わりに、カッコ内に指定して読み込むことも可能です: 37 | 38 | ```purescript 39 | module B where 40 | 41 | import A (runFoo) 42 | ``` 43 | 44 | 47 | 値、演算子(丸括弧で囲んでおく)、型コンストラクタ、データコンストラクタ、型クラスは全て明示的に読み込むことができます。型コンスタクタの後の丸括弧内に関連するデータコンストラクタを書き連ねることもでき、ピリオドを2つ(`..`)書くと、型コンストラクタの全てのデータコンストラクタがインポートされます。 48 | 49 | ```purescript 50 | module B where 51 | 52 | import A (runFoo, (.~), Foo(..), Bar(Bar)) 53 | ``` 54 | 55 | 58 | 型クラスをインポートするには`class`キーワードを使います。種の場合は`kind`です。 59 | 60 | ```purescript 61 | module B where 62 | 63 | import A (class Fab, kind Effect) 64 | ``` 65 | 66 | 69 | ### 除外インポート 70 | 71 | 74 | `hiding`キーワードを使って、openインポートから除外する名前を指定できます。これはモジュール間でインポートした名前が衝突することを防ぐときに便利です。 75 | 76 | ```purescript 77 | module C where 78 | 79 | import A hiding (runFoo) 80 | import B (runFoo) 81 | ``` 82 | 83 | 86 | 修飾インポート 87 | 88 | 91 | モジュールは修飾名付きでインポートすることもできます。つまり、モジュールの名前はそのままスコープに入れられるのではなく、別名として入れられます。 92 | 93 | 96 | 以下は修飾インポートが非常に便利に使える場面です。 97 | 98 | 101 | ### 総称関数の使用 102 | 103 | ``` purescript 104 | import Data.Map as Map 105 | 106 | a :: Map Int String 107 | a = Map.fromFoldable [ Tuple 1 "a" ] 108 | ``` 109 | 110 | 113 | いくつかのデータ構造モジュールは、別の`Foldable`データ構造からそのデータ構造のインスタンスを作成できる`fromFoldable`関数を持っています。どの`fromFoldable`関数が使われているのかを明確にするために、`Set.fromFoldable`のようにインポートの際に付けた修飾名のあとに関数名を書くことができます。 114 | 115 | 118 | 別の例として、ここでは架空のモジュールを使います: 119 | 120 | ``` purescript 121 | import MyWebFramework as MyWebFramework 122 | 123 | main :: Eff (dom :: DOM) Unit 124 | main = do 125 | elem <- domElementById "appContainer" 126 | MyWebFramework.run elem 127 | -- ^ this may be more clear than 128 | -- `run elem` 129 | ``` 130 | 131 | 134 | "run"はどこにでもありそうな名前なので、読む前にその関数の型を知らなければ、そのモジュールが`MyWebFramework`であると知るまでは`run`関数が何をするためのものなのかが不明確です。次の人がこのコードを読んだときの混乱を軽減するために、`MyWebFramework.run`のように修飾付きでインポートして使用することができます。 135 | 136 | 139 | ### 命名衝突の回避 140 | 141 | ```purescript 142 | module Main where 143 | 144 | import Data.Array as Array 145 | 146 | null = ... 147 | 148 | test = Array.null [1, 2, 3] 149 | ``` 150 | 151 | 154 | ここで、名前``null``は``Data.Array``の``null``と衝突していましたが、修飾インポートがこれを解決します。``Array.null``を使って``Data.Array.null``を参照することができます。 155 | 156 | 159 | 演算子も同じようにして参照することが可能です: 160 | 161 | ```purescript 162 | test' = Array.null ([1, 2, 3] Array.\\ [1, 2, 3]) 163 | ``` 164 | 165 | 168 | ### モジュールの統合 169 | 170 | 173 | 修飾インポートで同じ名前を用いることでモジュール同士を統合することができます。複数のモジュールをマージするときは、衝突を避けるために明示インポートの使用を考えてください: 174 | 175 | ```purescript 176 | module Main where 177 | 178 | import Data.String.Regex (split) as Re 179 | import Data.String.Regex.Flags (global) as Re 180 | import Data.String.Regex.Unsafe (unsafeRegex) as Re 181 | 182 | split = Re.split (Re.unsafeRegex "[,;:.]\\s+" Re.global) 183 | ``` 184 | 185 | 188 | ## モジュールの公開 189 | 190 | 193 | そのモジュールから何を公開するのかについて、公開リストを使用して制御できます。公開リストが使用された時、外部から見えるのは公開リストに含まれたもののみになります。例えば: 194 | 195 | ```purescript 196 | module A (exported) where 197 | 198 | exported :: Int -> Int 199 | exported = [...] 200 | 201 | notExported :: Int -> Int 202 | notExported = [...] 203 | ``` 204 | 205 | 208 | この場合、モジュール`A`をインポートしても`notExported`関数は見えません。 209 | 210 | 213 | 公開できる名前の種類はモジュールのインポートの場合と同じです。 214 | 215 | 218 | インポートされたモジュールは全体を再公開することができます: 219 | 220 | ```purescript 221 | module A (module B) where 222 | 223 | import B 224 | ``` 225 | 226 | 229 | 修飾・明示インポートも可能です: 230 | 231 | ```purescript 232 | module A (module MoreExports) where 233 | 234 | import A.Util (useful, usefulFn) as MoreExports 235 | import A.Type (ADatatype(..)) as MoreExports 236 | ``` 237 | 238 | 241 | 他のモジュールを再公開している時、自モジュールも公開リストに含めることで、全ての値や型も公開することができます: 242 | 243 | ```purescript 244 | module A (module A, module B) where 245 | 246 | import B 247 | 248 | data ... 249 | ``` 250 | 251 | 254 | ### 型クラスの公開 255 | 256 | 259 | 型クラスを公開するためには、単に型クラスとそのメンバをリストに含めます。残念ながら、型クラスのメンバ全てを一度に公開するようなショートハンドはありません。 260 | 261 | 264 | 例として、以下を考えます: 265 | 266 | ```purescript 267 | class Foldable f where 268 | foldr :: forall a b. (a -> b -> b) -> b -> (f a) -> b 269 | foldl :: forall a b. (b -> a -> b) -> b -> (f a) -> b 270 | foldMap :: forall a m. (Monoid m) => (a -> m) -> (f a) -> m 271 | ``` 272 | 273 | 276 | このとき、以下のようにして型クラスを公開します: 277 | 278 | ```purescript 279 | module Test (class Foldable, foldr, foldl, foldMap) where 280 | ``` 281 | 282 | 285 | 型クラスが公開される時には、その全てのメンバも公開されなければなりません。同様に、型クラスのメンバが公開されるときには、それが属する型クラスも公開されなければなりません。 286 | -------------------------------------------------------------------------------- /language/Pattern-Matching.md: -------------------------------------------------------------------------------- 1 | 4 | # パターンマッチ 5 | 6 | 9 | パターンマッチは値を分解して0個以上の式をスコープに入れます。パターンマッチは`case`キーワードにより導入されます。 10 | 11 | 14 | パターンマッチは一般的に次の形式で表されます: 15 | 16 | ```purescript 17 | case value of 18 | pattern -> result 19 | ... 20 | pattern -> result 21 | ``` 22 | 23 | 26 | 既に見たように、パターンマッチは関数の宣言にも用いられます: 27 | 28 | ```purescript 29 | fn pattern_1 ... pattern_n = result 30 | ``` 31 | 32 | 35 | パターンは関数を導入する際にも用いられます。例えば: 36 | 37 | ```purescript 38 | example x y z = x * y + z 39 | ``` 40 | 41 | 44 | 以下のようなパターンが存在します: 45 | 46 | 55 | - ワイルドカードパターン 56 | - リテラルパターン 57 | - 変数パターン 58 | - 配列パターン 59 | - コンストラクタパターン 60 | - レコードパターン 61 | - 名前付きパターン 62 | 63 | 66 | ガードとパターンガードもサポートされています。 67 | 68 | 72 | 網羅性検査器は網羅されていないパターンのために`Partial`制約を導入します。 73 | デフォルトでは、`Partial`制約が満たされないために、パターンが網羅されていなければなりません。あなたの関数にローカルな`Partial`制約を追加することで、エラーを非表示にすることが可能です。 74 | 75 | 79 | ワイルドカードパターン 80 | ---------------------- 81 | 82 | 85 | ワイルドカード`_`はどんな入力にもマッチし、スコープには何も入れません: 86 | 87 | ```purescript 88 | f _ = 0 89 | ``` 90 | 91 | 95 | リテラルパターン 96 | ---------------- 97 | 98 | 101 | リテラルパターンは定数とマッチさせるために用いられます: 102 | 103 | ```purescript 104 | f true = 0 105 | f false = 1 106 | 107 | g "Foo" = 0 108 | g _ = 1 109 | 110 | h 0 = 0 111 | h _ = 1 112 | ``` 113 | 114 | 118 | 変数パターン 119 | ------------ 120 | 121 | 124 | 変数パターンはどんな入力にもマッチし、それを変数の名前に束縛します: 125 | 126 | ```purescript 127 | double x = x * 2 128 | ``` 129 | 130 | 134 | 配列パターン 135 | ------------ 136 | 137 | 140 | 配列パターンは配列の入力にマッチし、その要素をスコープに入れます。例えば: 141 | 142 | ```purescript 143 | f [x] = x 144 | f [x, y] = x * y 145 | f _ = 0 146 | ``` 147 | 148 | 151 | ここで、1つ目のパターンは長さ1の配列にのみマッチし、その最初の要素をスコープに入れます。 152 | 153 | 156 | 2つ目のパターンは2つの要素を持つ配列にマッチし、その1番目と2番めの要素をスコープに入れます。 157 | 158 | 162 | コンストラクタパターン 163 | ---------------------- 164 | 165 | 168 | コンストラクタパターンはデータコンストラクタとその引数にマッチします: 169 | 170 | ```purescript 171 | data Foo = Foo String | Bar Number Boolean 172 | 173 | foo (Foo s) = true 174 | foo (Bar _ b) = b 175 | ``` 176 | 177 | 181 | レコードパターン 182 | ---------------- 183 | 184 | 187 | レコードパターンはレコードの入力にマッチし、そのプロパティをスコープに入れます: 188 | 189 | ```purescript 190 | f { foo: "Foo", bar: n } = n 191 | f _ = 0 192 | ``` 193 | 194 | 198 | ネストしたパターン 199 | ------------------ 200 | 201 | 204 | このパターンは既に紹介したパターンを組み合わせて表現されます。例えば: 205 | 206 | ```purescript 207 | f { arr: [x, _], take: "firstOfTwo" } = x 208 | f { arr: [_, x, _], take: "secondOfThree" } = x 209 | f _ = 0 210 | ``` 211 | 212 | 216 | 名前付きパターン 217 | ---------------- 218 | 219 | 222 | 名前付きパターンはネストしたパターンを使っているときに、新たな名前をスコープに入れます。``@``記号を用いてどんなパターンも名付けられます: 223 | 224 | ```purescript 225 | f a@[_, _] = a 226 | f _ = [] 227 | ``` 228 | 229 | 232 | ここで、1つ目のパターンでは、正確に2つの要素を持つ配列にマッチし、配列は変数`a`に束縛されます。 233 | 234 | 238 | ガード 239 | ------ 240 | 241 | 244 | ガードは条件式を用いて追加の制約を課すために用いられ、パターンの後にパイプを書くことで導入されます: 245 | 246 | ```purescript 247 | evens :: List Int -> Int 248 | evens Nil = 0 249 | evens (Cons x xs) | x `mod` 2 == 0 = 1 + evens xs 250 | evens (Cons _ xs) = evens xs 251 | ``` 252 | 253 | 256 | トップレベルで関数を定義するためにパターンを用いるとき、ガードは全パターンの後に現れます: 257 | 258 | ```purescript 259 | greater x y | x > y = true 260 | greater _ _ = false 261 | ``` 262 | 263 | 266 | 網羅的に考えるために、ガードは常に明らかに真になる条件を含まなければなりません。以下を完璧に作っても、コンパイラはそれが網羅的であることを検出できません: 267 | 268 | ```purescript 269 | compare :: Int -> Int -> Ordering 270 | compare x y 271 | | x > y = GT 272 | | x == y = EQ 273 | | x < y = LT 274 | ``` 275 | 276 | 279 | 以下はどちらも動き、最後のケースを含むことで網羅性が明確になっています: 280 | 281 | ```purescript 282 | compare x y 283 | | x > y = GT 284 | | x < y = LT 285 | | otherwise = EQ 286 | 287 | compare x y | x > y = GT 288 | compare x y | x < y = LT 289 | compare _ _ = EQ 290 | ``` 291 | 292 | 295 | (`otherwise`は`true`の別名で、一般的にはガード内で使われます。) 296 | 297 | 301 | パターンガード 302 | -------------- 303 | 304 | 307 | パターンガードは左矢印で表記されるパターンマッチでガードを拡張します。パターンガードは、矢印の右側の計算結果が左側のパターンとマッチする場合にのみ成功します。 308 | 309 | 313 | 例えば、関数`fn`を引数`x`に適用することができます。`fn`が`Just y`を返すときにのみ成功します。`y`は同時に束縛されます: 314 | 315 | ```purescript 316 | bar x | Just y <- fn x = ... -- x and y are both in scope here 317 | ``` 318 | 319 | 323 | パターンガードは、代数的データ型を使用する時、制御フローの特定の型を表現するために特に有用です。 324 | 325 | 328 | ガードに複数の式を追加するためにカンマを使うこともできます: 329 | 330 | ```purescript 331 | positiveLessThanFive :: Maybe Int -> Boolean 332 | positiveLessThanFive mInt 333 | | Just x <- mInt 334 | , x > 0 335 | , x < 5 = true 336 | | otherwise = false 337 | ``` 338 | -------------------------------------------------------------------------------- /language/README.md: -------------------------------------------------------------------------------- 1 | 4 | # PureScript言語リファレンス 5 | 6 | 9 | 例として、PureScriptの「Hello World」をお見せします: 10 | 11 | ```purescript 12 | module Main where 13 | 14 | import Effect.Console 15 | 16 | main = log "Hello, World!" 17 | ``` 18 | 19 | 22 | ## 別の例 23 | 24 | 27 | 以下のコードは`Person`データ型と`Person`の文字列表現を生成する関数を定義します: 28 | 29 | ```purescript 30 | data Person = Person { name :: String, age :: Int } 31 | 32 | showPerson :: Person -> String 33 | showPerson (Person o) = o.name <> ", aged " <> show o.age 34 | 35 | examplePerson :: Person 36 | examplePerson = Person { name: "Bonnie", age: 26 } 37 | ``` 38 | 39 | 42 | 各行は以下のように読むことができます: 43 | 44 | 51 | - `Person`は1つのコンストラクタを伴うデータ型であり、`Person`とも呼ばれる。 52 | - `Person`コンストラクタは2つのプロパティを持つオブジェクトを1つ受け取る。各プロパティは、`String`型の`name`と`Int`型の`age`である。 53 | - `showPerson`関数は`Person`を受け取り、`String`を返す。 54 | - `showPerson`関数は、引数の解析によって実現される。まずは`Person`コンストラクタにマッチし、その後にオブジェクトのアクセサと文字列結合の結果を返す。 55 | - `examplePerson`はPersonオブジェクトであり、`Person`コンストラクタに、nameの値としての文字列"Bonnie"とageの値としての整数26を与えることで作成される。 56 | 57 | 60 | 言語リファレンスの全容は以下に続きます: 61 | 62 | 72 | 1. [型](Types.md) 73 | 2. [構文](Syntax.md) 74 | 3. [型クラス](Type-Classes.md) 75 | 4. [パターンマッチ](Pattern-Matching.md) 76 | 5. [モジュール](Modules.md) 77 | 6. [外部関数インタフェース(FFI)](FFI.md) 78 | 7. [レコード](Records.md) 79 | 8. [Haskellとの違い](Differences-from-Haskell.md) 80 | -------------------------------------------------------------------------------- /language/Records.md: -------------------------------------------------------------------------------- 1 | 4 | # レコード 5 | 6 | 9 | レコードリテラルはJavaScriptのように波括弧で囲みます: 10 | 11 | ```purescript 12 | author :: { name :: String, interests :: Array String } 13 | author = 14 | { name: "Phil" 15 | , interests: ["Functional Programming", "JavaScript"] 16 | } 17 | ``` 18 | 19 | 22 | レコードのフィールドには、ドットの後にフィールドのラベルを続けることでアクセスできます: 23 | 24 | ```purescript 25 | > author.name 26 | "Phil" 27 | 28 | > author.interests 29 | ["Functional Programming","JavaScript"] 30 | ``` 31 | 32 | 35 | ## 種 36 | 37 | 40 | `{ ... }`は単なる`Record`型コンストラクタの糖衣構文なので、`{ language :: String }`は`Record ( language :: String )`と同じです。 41 | 42 | 45 | レコード型コンストラクタは型の列によってパラメータ化されています。型注釈では、`Record`は種`# Type -> Type`を持っています。これは型の列を取って型にするということです。 46 | 47 | 50 | `( language :: String )`は型の列(`# Type`など)を表すので、型を構築するために`Record`を通します。すなわち、`Record ( language :: String )`です。 51 | 52 | 55 | ## 拡張レコード 56 | 57 | 60 | 拡張可能レコードを定義することが可能です: 61 | 62 | ```purescript 63 | type Lang l = { language :: String | l } 64 | ``` 65 | 66 | 69 | これを以下のようにして拡張することができます: 70 | 71 | ```purescript 72 | type Language = Lang ( country :: String ) 73 | ``` 74 | 75 | 78 | `Language`型シノニムは`{ language :: String, country :: String }`と等しくなります。`l`はレコード型ではなく列種であるため、丸括弧は拡張のために使われなければならないことに注意してください。 79 | 80 | 83 | ## ワイルドカード 84 | 85 | 88 | ワイルドカードを含むレコードリテラルはレコードを生成する関数を生成するために使えます: 89 | 90 | ```purescript 91 | { foo: _, bar: _ } 92 | ``` 93 | 94 | 97 | これは次と同じです: 98 | 99 | ```purescript 100 | \foo bar -> { foo: foo, bar: bar } 101 | ``` 102 | 103 | 106 | ## レコード更新 107 | 108 | 111 | PureScriptはHaskellと似たレコード更新の構文も提供します: 112 | 113 | ```purescript 114 | setX :: Number -> Point -> Point 115 | setX val point = point { x = val } 116 | ``` 117 | 118 | 121 | ネストしたレコードの更新も可能です: 122 | 123 | ```purescript 124 | setPersonPostcode :: PostCode -> Person -> Person 125 | setPersonPostcode pc p = p { address { postCode = pc } } 126 | ``` 127 | 128 | 131 | ## フィールド名 132 | 133 | 136 | タイトルケースやスペースを含む文字列などでシンボルが不正な値識別子である場合、それを二重引用符で囲むことによって識別が可能です: 137 | 138 | ```purescript 139 | author' :: { "Name" :: String, "Personal Interests" :: Array String } 140 | author' = { "Name": "Phil", "Personal Interests": ["Functional Programming", "JavaScript"] } 141 | 142 | > author'."Name" 143 | "Phil" 144 | 145 | > (author' { "Name" = "John" })."Name" 146 | "John" 147 | ``` 148 | 149 | 152 | JavaScriptにコンパイルされる場合、JavaScriptで特別な意味を持つシンボルも許可されることを考慮してください。例えば`__proto__`などです。 153 | 154 | 161 | ```purescript 162 | oops = {__proto__: unsafeCoerce ""}.__proto__.constructor.constructor "alert('lol')" 0 163 | -- ウェブページに読み込まれた時、"lol"をブラウザのダイアログボックスに表示します。 164 | -- これは副作用を生む振る舞いにも関わらず、この式は純粋に見えます。 165 | ``` 166 | -------------------------------------------------------------------------------- /language/Type-Classes.md: -------------------------------------------------------------------------------- 1 | 4 | # 型クラス 5 | 6 | 9 | PureScriptは`class`と`instance`のキーワードによって型クラスをサポートしています。 10 | 11 | 14 | クラスインスタンスに現れる型は`String`、`Number`、`Boolean`または`C t1 ... tn`のような形でなければなりません。`C`は型コンストラクタです(`->`と`t_i`は 15 | 同じ形式の型)。 16 | 17 | 20 | 以下は`Show`型クラスのインスタンス`String`、`Boolean`、`Array`の例です: 21 | 22 | ```purescript 23 | class Show a where 24 | show :: a -> String 25 | 26 | instance showString :: Show String where 27 | show s = s 28 | 29 | instance showBoolean :: Show Boolean where 30 | show true = "true" 31 | show false = "false" 32 | 33 | instance showArray :: (Show a) => Show (Array a) where 34 | show xs = "[" <> joinWith ", " (map show xs) <> "]" 35 | example = show [true, false] 36 | ``` 37 | 38 | 39 | 42 | インスタンスの重複はPureScriptでは許されていません。インスタンスの重複を書くためには、インスタンスチェーンを使う必要があります。 43 | 44 | 47 | ## インスタンスチェーン 48 | 49 | 52 | PureScriptでは、引数によってマッチするインスタンスのグループを処理するインスタンスチェーンを実装しています。これはインスタンスを選ぶときに制約が考慮されないことを意味します。しかし、`else`キーワードを使用して、上から下の順でマッチするインスタンスのチェーンを書くことが可能です。 53 | 54 | 57 | 以下は`MyShow`型クラスのインスタンス`String`、`Boolean`と任意の型の例です。 58 | 59 | ```purescript 60 | class MyShow a where 61 | myShow :: a -> String 62 | 63 | instance showString :: MyShow String where 64 | myShow s = s 65 | 66 | else instance showBoolean :: MyShow Boolean where 67 | myShow true = "true" 68 | myShow false = "false" 69 | 70 | else instance showA :: MyShow a where 71 | myShow _ = "Invalid" 72 | 73 | data MysteryItem = MysteryItem 74 | 75 | main = do 76 | log $ myShow "hello" -- hello 77 | log $ myShow true -- true 78 | log $ myShow MysteryItem -- Invalid 79 | ``` 80 | 81 | 84 | ## 多変数型クラス 85 | 86 | 89 | TODO。 今は[PureScript by Example](https://leanpub.com/purescript/read#leanpub-auto-multi-parameter-type-classes)を参照してください。 90 | 91 | 94 | ## スーパークラス 95 | 96 | 99 | スーパークラスの包含はクラス宣言の中で逆向きの太矢印`<=`を使って示します: 100 | 101 | ```purescript 102 | class (Monad m) <= MonadFail m where 103 | fail :: forall a. String -> m a 104 | ``` 105 | 106 | 109 | この例のコードは`Monad`をスーパークラスに持つ`MonadFail`クラスを宣言しています。`MonadFail`のインスタンスを定義する任意の型は`Monad`のインスタンスも定義していることを要求されます。 110 | 111 | 114 | スーパークラスのインスタンスはサブクラスのインスタンスを探すときに使用されます。例えば、以下のコードでは、`Applicative`は`Monad`のスーパークラス、つまり`MonadFail`のスーパークラスであるため、`pure`関数によって導入された`Applicative`制約は解除できます。 115 | 116 | ```purescript 117 | assert :: forall m. (MonadFail m) => Boolean -> m Unit 118 | assert true = pure unit 119 | assert false = fail "Assertion failed" 120 | ``` 121 | 122 | 125 | ## 孤児インスタンス 126 | 127 | 130 | クラスを定義したモジュールと型を定義したモジュールの両方の外側で定義された型クラスのインスタンスを*孤児インスタンス*と呼びます。Haskellを含むいくつかのプログラミング言語は、孤児インスタンスを警告を伴って許可します。しかしPureScriptではこれを禁止しています。PureScriptで孤児インスタンスを定義しようとすると、あなたのプログラムは型検査を通りません。 131 | 132 | 135 | 例えば、`Semigroup`型クラスはモジュール`Data.Semigroup`の中で定義されていて、`Int`型はモジュール`Prim`の中で定義されています。もし私達が次のように`Semigroup Int`インスタンスを定義しようとすると: 136 | 137 | ```purescript 138 | module MyModule where 139 | 140 | import Prelude 141 | 142 | instance semigroupInt :: Semigroup Int where 143 | append = (+) 144 | ``` 145 | 146 | 149 | これは失敗します。`semigroupInt`は孤児インスタンスだからです。`newtype`を使うことでこれを回避できます: 150 | 151 | ```purescript 152 | module MyModule where 153 | 154 | import Prelude 155 | 156 | newtype AddInt = AddInt Int 157 | 158 | instance semigroupAddInt :: Semigroup AddInt where 159 | append (AddInt x) (AddInt y) = AddInt (x + y) 160 | ``` 161 | 162 | 165 | 実は、この`AddInt`に似た型が`monoid`パッケージの`Data.Monoid.Additive`で提供されています。 166 | 167 | 170 | 多変数型クラスのために、孤児インスタンス検査は、そのインスタンスがそのクラスと同じモジュール内にあるか、そのインスタンスに存在する型の少なくとも1つと同じモジュール内にあることを要求します。 171 | 172 | 175 | ## 関数型依存性 176 | 177 | 180 | 一般的に、複数の引数を持つクラスのインスタンスは、マッチして具象になるために引数の一部のみを必要とします。どのパラメータがインスタンスヘッド内の他のパラメータを決定できるかという宣言を関数型依存性と呼びます。例えば: 181 | 182 | ```purescript 183 | class TypeEquals a b | a -> b, b -> a where 184 | to :: a -> b 185 | from :: b -> a 186 | 187 | instance refl :: TypeEquals a a where 188 | to a = a 189 | from a = a 190 | ``` 191 | 192 | 195 | `|`記号は関数型依存性の始まりを意味し、1つ以上ある場合はカンマで区切ります。この場合、1つ目の引数は2つ目の型を、2つ目の引数は1つ目の型を決定します。 196 | 197 | 200 | 関数型依存性はさまざまな`Prim`型クラスで特に便利です。例えば、[`Prim.Row.Cons`](https://pursuit.purescript.org/builtins/docs/Prim.Row#t:Cons)などです。 201 | 202 | 205 | 本の[該当する章(PureScript by Example)](https://leanpub.com/purescript/read#leanpub-auto-functional-dependencies)も見てください。 206 | 207 | 210 | ## 型クラス導出 211 | 212 | 215 | いくつかの型クラスインスタンスはPureScriptコンパイラによって自動的に導出されます。型クラスインスタンスを導出するためには、`derive instance`キーワードを使います: 216 | 217 | ```purescript 218 | newtype Person = Person { name :: String, age :: Int } 219 | 220 | derive instance eqPerson :: Eq Person 221 | derive instance ordPerson :: Ord Person 222 | ``` 223 | 224 | 227 | 現在、以下の型クラスが導出可能です: 228 | 229 | 236 | - [Data.Generic.Rep (Genericクラス)](https://pursuit.purescript.org/packages/purescript-generics-rep/6.0.0/docs/Data.Generic.Rep#t:Generic) 237 | - [Data.Eq (Eqクラス)](https://pursuit.purescript.org/packages/purescript-prelude/4.1.0/docs/Data.Eq#t:Eq) 238 | - [Data.Ord (Ordクラス)](https://pursuit.purescript.org/packages/purescript-prelude/4.1.0/docs/Data.Ord#t:Ord) 239 | - [Data.Functor (Functorクラス)](https://pursuit.purescript.org/packages/purescript-prelude/4.1.0/docs/Data.Functor#t:Functor) 240 | - [Data.Newtype (Newtypeクラス)](https://pursuit.purescript.org/packages/purescript-newtype/3.0.0/docs/Data.Newtype#t:Newtype) 241 | 242 | 245 | ## コンパイラで解決可能な型クラス 246 | 247 | 250 | いくつかの型クラスは`derive instance`のようなキーワードを書くことなくPureScriptコンパイラによって自動的に解決可能です。 251 | 252 | ``` purescript 253 | foo :: forall t. (Warn "Custom warning message") => t -> t 254 | foo x = x 255 | ``` 256 | 257 | 260 | 自動的に解決される型は[Prim](https://pursuit.purescript.org/builtins/docs/Prim)モジュールに含まれています: 261 | 262 | 265 | 記号関連のクラス 266 | 267 | - [`IsSymbol`](https://pursuit.purescript.org/packages/purescript-symbols/3.0.0/docs/Data.Symbol#t:IsSymbol) 268 | - [`Append`](https://pursuit.purescript.org/builtins/docs/Prim.Symbol#t:Append) 269 | - [`Compare`](https://pursuit.purescript.org/builtins/docs/Prim.Symbol#t:Compare) 270 | - [`Cons`](https://pursuit.purescript.org/builtins/docs/Prim.Symbol#t:Cons) 271 | 272 | [Prim.Row](https://pursuit.purescript.org/builtins/docs/Prim.Row) 273 | 274 | - [`Cons`](https://pursuit.purescript.org/builtins/docs/Prim.Row#t:Cons) 275 | - [`Union`](https://pursuit.purescript.org/builtins/docs/Prim.Row#t:Union) 276 | - [`Nub`](https://pursuit.purescript.org/builtins/docs/Prim.Row#t:Nub) 277 | - [`Lacks`](https://pursuit.purescript.org/builtins/docs/Prim.Row#t:Lacks) 278 | 279 | [Prim.RowList](https://pursuit.purescript.org/builtins/docs/Prim.RowList) 280 | 281 | - [`RowToList`](https://pursuit.purescript.org/builtins/docs/Prim.RowList#t:RowToList) 282 | 283 | 286 | その他のクラス 287 | 288 | - [`Partial`](https://pursuit.purescript.org/builtins/docs/Prim#t:Partial) 289 | - [`Fail`](https://pursuit.purescript.org/builtins/docs/Prim.TypeError#t:Fail) 290 | - [`Warn`](https://pursuit.purescript.org/builtins/docs/Prim.TypeError#t:Warn) 291 | --------------------------------------------------------------------------------