PureScript Documentation Release 0.5.0 Phil Freeman November 05, 2014
Transcription
PureScript Documentation Release 0.5.0 Phil Freeman November 05, 2014
PureScript Documentation Release 0.5.0 Phil Freeman November 05, 2014 Contents 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 4 5 Getting Started 2.1 Compiler Installation . . . . . . . 2.2 Creating a new PureScript project 2.3 Compiler usage . . . . . . . . . . 2.4 psc-make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 7 7 8 Types 3.1 Primitive Types . . . 3.2 Arrays . . . . . . . 3.3 Records . . . . . . . 3.4 Tagged Unions . . . 3.5 Newtypes . . . . . . 3.6 Functions . . . . . . 3.7 Polymorphic Types . 3.8 Row Polymorphism 3.9 Rank N Types . . . 3.10 Rows . . . . . . . . 3.11 Type Synonyms . . 3.12 Constrained Types . 3.13 Type Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 9 10 10 10 10 11 11 11 12 12 12 4 Kind System 4.1 Row Kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Quantification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 13 13 5 Syntax 5.1 Whitespace Rules 5.2 Operators . . . . . 5.3 Literal Values . . . 5.4 Array Literals . . . 5.5 Record Literals . . 5.6 Array Indexing . . 15 15 15 16 16 16 17 2 3 Introduction 1.1 Motivation . . . . 1.2 Hello, PureScript! 1.3 Another Example . 1.4 Related Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i 5.7 5.8 5.9 5.10 5.11 5.12 5.13 5.14 Property Accessors . . . . Functions . . . . . . . . . If-Then-Else Expressions Do Notation . . . . . . . Operators . . . . . . . . . Record Updates . . . . . Let Bindings . . . . . . . Comments . . . . . . . . . . . . . . . . 17 17 17 18 18 19 19 20 6 Type Classes 6.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Superclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Type Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 21 21 22 7 Pattern Matching 7.1 Wildcard Patterns . . 7.2 Literal Patterns . . . 7.3 Variable Patterns . . 7.4 Array Patterns . . . 7.5 Cons Patterns . . . . 7.6 Constructor patterns 7.7 Record Patterns . . . 7.8 Nested Patterns . . . 7.9 Named Patterns . . . 7.10 Guards . . . . . . . . . . . . . . . . . 23 23 24 24 24 24 24 25 25 25 25 8 Modules 8.1 Importing Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Qualified Imports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3 Module Exports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 27 27 28 9 Foreign Function Interface 9.1 Importing Values . . . . . . . . 9.2 Inline Javascript . . . . . . . . 9.3 Importing Types . . . . . . . . 9.4 Importing Type Class Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 29 29 29 29 10 Module Documentation 10.1 Module Prelude . . . . . . . . . . 10.2 Module Data.Function . . . . . . . 10.3 Module Data.Eq . . . . . . . . . . 10.4 Module Prelude.Unsafe . . . . . . 10.5 Module Control.Monad.Eff . . . . 10.6 Module Control.Monad.Eff.Unsafe 10.7 Module Debug.Trace . . . . . . . . 10.8 Module Control.Monad.ST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 31 34 36 36 36 37 37 37 11 Indices and tables ii . . . . 39 PureScript Documentation, Release 0.5.0 Contents: Contents 1 PureScript Documentation, Release 0.5.0 2 Contents CHAPTER 1 Introduction PureScript is a small strongly, statically typed compile-to-JS language with a number of interesting features, such as: • Type Inference • Higher Kinded Polymorphism • Support for basic Javascript types • Extensible records • Extensible effects • Optimizer rules for generation of efficient Javascript • Pattern matching • Simple FFI • Modules • Rank N Types • Do Notation • Tail-call elimination • Type Classes 1.1 Motivation I was looking for a simple functional language which would compile to JavaScript and have the following characteristics: • Generate simple readable Javascript • Provide the ability to compile to tight loops if necessary • Reasonable type system • Ideally, written in a programming language I would enjoy working in • Provides a simple interface to existing Javascript code I didn’t find exactly what I was looking for, so I wrote PureScript. It doesn’t have everything right now, but it should serve as a simple core on which to develop new ideas. PureScript was originally designed to implement purely functional core logic. However, recent additions to the compiler and libraries now also make it a good option for general-purpose programming. 3 PureScript Documentation, Release 0.5.0 PureScript can also be seen as a trade-off between a theoretically ideal language and one which generates reasonably high performance code. 1.2 Hello, PureScript! As an introductory example, here is the usual “Hello World” written in PureScript: module Main where import Debug.Trace main = trace "Hello, World!" which compiles to the following Javascript, ignoring the Prelude: var Main; (function (Main) { var main = trace("Hello, World!"); Main.main = main; })(Main = Main || {}); The following command will compile and execute the PureScript code above: psc input.purs --main | node 1.3 Another Example The following code defines a Person data type and a function to generate a string representation for a Person: data Person = Person { name :: String, age :: Number } showPerson :: Person -> String showPerson (Person o) = o.name ++ ", aged " ++ show o.age examplePerson :: Person examplePerson = Person { name: "Bonnie", age: 26 } Line by line, this reads as follows: • Person is a data type with one constructor, also called Person • The Person constructor takes an object with two properties, name which is a String, and age which is a Number • The showPerson function takes a Person and returns a String • showPerson works by case analysis on its argument, first matching the constructor Person and then using string concatenation and object accessors to return its result. • examplePerson is a Person object, made with the Person constructor and given the String “Bonnie” for the name value and the Number 26 for the age value. The generated Javascript looks like this: var Person = function (value) { return { ctor: ’Person’, values: [value] }; }; 4 Chapter 1. Introduction PureScript Documentation, Release 0.5.0 function showPerson(_1) { return _1.values[0].name + ", aged " + numberToString(_1.values[0].age); }; var examplePerson = Person({ name: "Bonnie", age: 26 }); 1.4 Related Projects 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. 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) Projects such as Haste, Fay and GHCJS aim to use some combination of the GHC compiler itself and/or its intermediate representation, Core, to perform some of the tasks involved in compilation such as parsing and type checking. This usually 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. 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. 1.4. Related Projects 5 PureScript Documentation, Release 0.5.0 6 Chapter 1. Introduction CHAPTER 2 Getting Started 2.1 Compiler Installation If you have the Haskell Plaform installed, then you can install the latest released version from Hackage: cabal update cabal install purescript If you would like to build the latest version of the code, clone this repository and build: git clone git@github.com:purescript/purescript.git cd purescript cabal configure --enable-tests cabal build cabal test cabal install Alternatively, consider installing PureScript in a Cabal sandbox using cabal sandbox init. 2.2 Creating a new PureScript project You can create a new PureScript project using grunt-init and this PureScript project template. This will give you a project that uses Grunt as its build tool and Bower for dependency management. See the README for step-by-step instructions. 2.3 Compiler usage The psc executable takes a list of PureScript source files as arguments and by default writes out its errors or output to the console. The following options are supported: --stdin Read input from standard input instead of from files. --output Write the generated Javascript to the specified file. --externs Write a list of foreign imports declarations to the specified file in addition to generating Javascript output. --no-tco Turn off tail-call elimination. 7 PureScript Documentation, Release 0.5.0 --no-prelude Do not include the Prelude in the generated Javascript. --no-magic-do Turn off optimizations which inline calls to >>= for the Eff monad. --no-opts Disable all optimizations. --main Generate a call to main in the specified module after all other generated Javascript. Defaults to Main if the option is used but no value is provided. --module If specified, any code which is not referenced transitively from this module will be removed. This argument can be used multiple times. --codegen A list of modules for which Javascript and externs should be generated. This argument can be used multiple times. --browser-namespace Specify the namespace that PureScript modules will be exported to when running in the browser. --verbose-errors Generate verbose error messages. 2.4 psc-make The psc-make executable makes CommonJS modules and supports incremental compilation. Unlike psc, it does not do dead code elimination. The following command line options are supported: 8 --output=VAL The output directory. Default: output. --verbose-errors Display verbose error messages. --help=FMT Show this help in format FMT (pager, plain, or groff). Default: pager. --no-magic-do Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad. --no-opts Skip the optimization phase. --no-prelude Omit the Prelude. --no-tco Disable tail call optimizations Chapter 2. Getting Started CHAPTER 3 Types The type system defines the following types: • Primitive Types: Number, String, Boolean • Arrays • Records • Tagged Unions • Newtypes • Functions • Polymorphic Types • Constrained Types • Type Synonyms • Rows 3.1 Primitive Types The three primitive types String, Number and Boolean correspond to their Javascript equivalents at runtime. 3.2 Arrays PureScript arrays correspond to Javascript arrays at runtime, but all elements in an array must have the same type. 3.3 Records PureScript records correspond to Javascript objects. They may have zero or more named fields, each with their own types. 9 PureScript Documentation, Release 0.5.0 3.4 Tagged Unions Tagged unions consist of one or more constructors, each of which takes zero or more arguments. Tagged unions can only be created using their constructors, and deconstructed through pattern matching (see later). For example: data Foo = Foo | Bar String runFoo Foo = "It’s a Foo" runFoo (Bar s) = "It’s a Bar. The string is " ++ s test = runFoo Foo ++ runFoo (Bar "Test") In the example, Foo is a tagged union type which has two constructors. Its first constructor Foo takes no arguments, and its second Bar takes one, which must be a String. runFoo is an example of pattern matching on a tagged union type to discover its constructor, and the last line shows how to construct values of type Foo. 3.5 Newtypes Newtypes are like data types introduced with the data keyword, but are restricted to a single contructor which contains a single argument. Newtypes are introduced with the newtype keyword: newtype Percentage = Percentage Number The representation of a newtype at runtime is the same as the underlying data type. For example, a value of type Percentage is just a JavaScript number at runtime. Newtypes can be assigned their own type class instances, so for example, Percentage can be given its own Show instance: instance showPercentage :: Show Percentage where show (Percentage n) = show n ++ "%" 3.6 Functions Functions in PureScript are like their Javascript counterparts, but always have exactly one argument. 3.7 Polymorphic Types Expressions defined at the top level may have polymorphic types. Here is an example: identity x = x identity is inferred to have (polymorphic) type forall t0. t0 -> t0. This means that for any type t0, identity can be given a value of type t0 and will give back a value of the same type. A type annotation can also be provided: 10 Chapter 3. Types PureScript Documentation, Release 0.5.0 identity :: forall a. a -> a identity x = x 3.8 Row Polymorphism Polymorphism is not limited to abstracting over types. Values may also be polymorphic in types with other kinds, such as rows or effects (see “Kind System”). For example, the following function accesses two properties on a record: addProps o = o.foo + o.bar The inferred type of addProps is: forall r. { foo :: Number, bar :: Number | r } -> Number Here, the type variable r has kind # * - it represents a row of types. It can be instantiated with any row of named types. In other words, addProps accepts any record which has properties foo and bar, and any other record properties. Therefore, the following application compiles: addProps { foo: 1, bar: 2, baz: 3 } even though the type of addProps does not mention the property baz. However, the following does not compile: addProps { foo: 1 } since the bar property is missing. 3.9 Rank N Types It is also possible for the forall quantifier to appear on the left of a function arrow, inside types record fields and data constructors, and in type synonyms. In most cases, a type annotation is necessary when using this feature. As an example, we can pass a polymorphic function as an argument to another function: poly :: (forall a. a -> a) -> Boolean poly f = (f 0 < 1) == f true Notice that the polymorphic function’s type argument is instantiated to both Number and Boolean. An argument to poly must indeed be polymorphic. For example, the following fails: test = poly (\n -> n + 1) since the skolemized type variable a does not unify with Number. 3.10 Rows A row of types represents an unordered collection of named types without duplicates. 3.8. Row Polymorphism 11 PureScript Documentation, Release 0.5.0 Rows have kind # k for some kind k, and so values do not have types which are rows. Rather, rows can be used in type signatures to define record types or other type where labelled, unordered types are useful. To denote a closed row, separate the fields with commas, with each label separated from its type with a double colon: (name :: String, age :: Number) It may be necessary, depending on the context, to surround a row in parentheses. To denote an open row (i.e. one which may unify with another row to add new fields), separate the specified terms from a row variable by a pipe: (name :: String, age :: Number | r) 3.11 Type Synonyms For convenience, it is possible to declare a synonym for a type using the type keyword. Type synonyms can include type arguments. For example: type Foo = { foo :: Number, bar :: Number } addFoo :: Foo -> Number addFoo = \o -> o.foo + o.bar 3.12 Constrained Types Polymorphic types may be predicated on one or more constraints. See the chapter on type classes for more information. 3.13 Type Annotations Most types can be inferred (not including Rank N Types and constrained types), but annotations can optionally be provided using a double-colon: one = 1 :: Number 12 Chapter 3. Types CHAPTER 4 Kind System The kind system defines the following kinds: • *, the kind of types. • !, the kind of effects. • Arrow kinds k1 -> k2 • Row kinds # k 4.1 Row Kinds The kind # k of rows is used to classify labelled, unordered collections of types of kind k. For example # * is the kind of rows of types, as used to define records, and # ! is the kind of rows of effects, used to define the monad Eff of extensible effects. 4.2 Quantification A type variable can refer to not only a type or a row, but a type constructor, or row constructor etc., and type variables with those kinds can be bound inside a forall quantifier. 13 PureScript Documentation, Release 0.5.0 14 Chapter 4. Kind System CHAPTER 5 Syntax 5.1 Whitespace Rules Syntax is whitespace sensitive. The general rule of thumb is that declarations which span multiple lines should be indented past the column on which they were first defined on their subsequent lines. That is, the following is valid: foo = bar(x) + baz(x) But this is not: foo = bar(x) + baz(x) 5.2 Operators Binary operators in PureScript are just regular functions. The Prelude defines a number of operators which correspond to Javascript’s operators. The Prelude defines the following functions which correspond to Javascript’s unary operators: Function negate not complement Operator ! ~ Meaning Numeric negation Boolean negation Binary negation and the following binary operators: 15 PureScript Documentation, Release 0.5.0 Function + * / % == /= < <= > >= && || & | ^ shl shr zshr ++ JS Operator + * / % == != < <= > >= && || & | ^ << >> >>> + Meaning Numeric addition Numeric subtraction Numeric multiplication Numeric division Numeric modulus Equality check Inequality check Less than Less than or equal Greater than Greater than or equal Boolean AND Boolean OR Binary AND Binary OR Binary XOR Shift Left Shift Right Zero-Fill Shift Right String concatenation 5.3 Literal Values Numeric literals can be integers or floating point numbers. Numbers in hexadecimal notation should be preceded by the characters 0x: 16 16.0 0xF0 String literals are enclosed in double-quotes and may extend over multiple lines. Line breaks should be surrounded by slashes as follows: "Hello World" "Hello \ \World" The two boolean literals are true and false. 5.4 Array Literals Array literals are surrounded by square brackets, as in Javascript: [] [1, 2, 3] 5.5 Record Literals Record literals are surrounded by braces, as in Javascript: 16 Chapter 5. Syntax PureScript Documentation, Release 0.5.0 {} { foo: "Foo", bar: 1 } 5.6 Array Indexing The Prelude.Unsafe module defines the unsafeIndex function which retrieves the element of an array at an index: unsafeIndex :: forall a. [a] -> Number -> a The code generator will turn the expression unsafeIndex arr index into the simplified Javascript arr[index]. The purescript-array core library defines an alternative safe version !! of unsafeIndex which checks arrays bounds and returns a value of type Maybe a. 5.7 Property Accessors To access a property of a record, use a dot, followed by the property name, as in Javascript: rec.propertyName 5.8 Functions Functions are introduced by using a backslash followed by a list of argument names: example1 = \a b -> a + b which would correspond to the following Javascript: function example1(a) { return function (b) { return a + b; } } Function application is indicated by just the juxtaposition of a function with its arguments: example1 10 20 Functions can also be defined at the top level by providing a list of patterns and an optional guard on the left hand side of the equals sign: f [] [] = [] f (x:xs) (y:ys) = x + y : f xs ys 5.9 If-Then-Else Expressions The if, then and else keywords can be used to create conditional expressions. In this case, the else block is always required. 5.6. Array Indexing 17 PureScript Documentation, Release 0.5.0 For example: conditional = if 2 > 1 then "ok" else "oops" 5.10 Do Notation The do keyword introduces simple syntactic sugar for monadic expressions. Here is an example, using the maybe monad: data Maybe a = Nothing | Just a isEven :: Number -> Maybe Unit isEven n | n % 2 == 0 = Just unit isEven _ = Nothing evenSum a b = do n <- a m <- b let sum = n + m isEven sum return sum isEven adds two values of type Maybe Number and returns their sum, if the sum is even. If the sum is odd, evenSum returns Nothing. When using do notation, the corresponding type constructor must be an instance of the Prelude.Monad type class. Statements can have the following form: • a <- x which desugars to x >>= \a -> ... • x which desugars to x >>= \_ -> ... or just x if this is the last statement. • A let binding let a = x where a can be either a name or a binder. Note the lack of the in keyword. The example evenSum desugars to: evenSum a b = a >>= \n -> b >>= \m -> let sum = n + m in isEven sum >>= \_ -> return sum Binders can be used on the left hand side of <- or =. For example: test arr = do (x:y:_) <- arr ret (x + y) A pattern match failure will generate a runtime exception, just as in the case of a regular case statement. 5.11 Operators User-defined infix operators can be created by enclosing names in parentheses. E.g. to create an infix synonym for the Data.Array.range function: 18 Chapter 5. Syntax PureScript Documentation, Release 0.5.0 (..) :: Number -> Number -> [Number] (..) = Data.Array.range This function can be used as follows: oneToTen = 1 .. 10 Regular functions can be used as operators by enclosing their names in backticks: foo x y = x * y + y test = 10 ‘foo‘ 20 Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates: infix 5 .. infixl 7 %% infixr 9 ^^ 5.12 Record Updates Properties on records can be updated using the following syntax: o { key = value, ..., key = value } For example, the following function increments the foo property on its argument: incr o = o { foo = o.foo + 1 } 5.13 Let Bindings The let keywords a collection of local declarations, which may be mutually recursive, and which may include type declarations: factorial :: Number -> Number factorial = let go :: Number -> Number -> Number go acc 1 = acc go acc n = go (acc * n) (n - 1) in go 1 The where keyword can also be used to introduce local declarations at the end of a value declaration: factorial :: Number -> Number factorial = go 1 where go :: Number -> Number -> Number go acc 1 = acc go acc n = go (acc * n) (n - 1) 5.12. Record Updates 19 PureScript Documentation, Release 0.5.0 5.14 Comments A single line comment starts with --: -- This is a comment Multi-line comments are enclosed in {- and -}. These can be nested: {- Comment {- nested comment -} continued comment -} 20 Chapter 5. Syntax CHAPTER 6 Type Classes PureScript has basic support for type classes via the class and instance keywords. Types appearing in class instances are must be of the form String, Number, Boolean, or C t1 ... C is a type constructor (including [] and -> and t_i are types of the same form). tn where Type class instances are resolved based on the order in which they appeared in the source files. Overlapping instances will result in a compilation error. 6.1 Example Here is an example of the Show typeclass, with instances for String, Booleans and []: class Show a where show :: a -> String instance showString :: Show String where show s = s instance showBoolean :: Show Boolean where show true = "true" show false = "false" instance showArray :: (Show a) => Show [a] where show [] = "[]" show (x:xs) = show x ++ " : " ++ showArray xs example = show [true, false] 6.2 Superclasses Superclass implications can be indicated in a class declaration with a backwards fat arrow <=: class (Monad m) <= MonadFail m where fail :: forall a. String -> m a Superclass instances will be used when searching for an instance of a subclass. For example, in the code below, the Monad constraint introduced by the return function can be discharged since Monad is a superclass of MonadFail: 21 PureScript Documentation, Release 0.5.0 assert :: forall m. (MonadFail m) => Boolean -> m Unit assert true = return unit assert false = fail "Assertion failed" 6.3 Type Annotations A constrained type will never be inferred for a top-level declaration without an explicit type signature. 22 Chapter 6. Type Classes CHAPTER 7 Pattern Matching Pattern matching deconstructs a value to bring zero or more expressions into scope. Pattern matches are introduced with the case keyword. Pattern matches have the following general form: case value of pattern -> result ... pattern -> result Pattern matching can also be used in the declaration of functions, as we have already seen: fn pattern_1 ... pattern_n = result Patterns can also be used when introducing functions. For example: example x y z = x * y + z The following pattern types are supported: • Wildcard pattern • Literal patterns • Variable pattern • Array patterns • Cons patterns • Constructor patterns • Record patterns • Named patterns • Guards Patterns need not be exhaustive. A pattern match failed exception will be thrown at runtime if no pattern matches the input. 7.1 Wildcard Patterns The wilcard _ matches any input and brings nothing into scope: 23 PureScript Documentation, Release 0.5.0 f _ = 0 7.2 Literal Patterns Literal patterns are provided to match on primitives: f true = 0 f false = 1 g "Foo" = 0 g _ = 1 h 0 = 0 h _ = 1 7.3 Variable Patterns A variable pattern matches any input and binds that input to its name: double x = x * 2 7.4 Array Patterns Array patterns match an input which is an array, and bring its elements into scope. For example: f [x] = x f [x, y] = x * y f _ = 0 Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope. The second pattern matches arrays with two elements, and brings the first and second elements into scope. 7.5 Cons Patterns The head and tail of a non-empty array can be matched by using a cons pattern: sum [] = 0 sum (x : xs) = x + sum xs : associates to the right: addPairs (x : y : xs) = x * y + addPairs xs addPairs _ = 0 7.6 Constructor patterns Constructor patterns match a data constructor and its arguments: 24 Chapter 7. Pattern Matching PureScript Documentation, Release 0.5.0 data Foo = Foo String | Bar Number Boolean foo (Foo s) = true foo (Bar _ b) = b 7.7 Record Patterns Record patterns match an input which is a record, and bring its properties into scope: f { foo = "Foo", bar = n } = n f _ = 0 7.8 Nested Patterns The patterns above can be combined to create larger patterns. For example: f { arr = x : _, take = "car" } = x f { arr = _ : x : _, take = "cadr" } = x f _ = 0 7.9 Named Patterns Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the @ symbol: f a@(_ : _ : _) = true f _ = false Here, in the first pattern, any array with two or more elements will be matched and bound to the variable a. 7.10 Guards Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern: evens [] = 0 evens (x : xs) | x % 2 == 0 = 1 + evens xs evens (_ : xs) = evens xs When using patterns to define a function at the top level, guards appear after all patterns: greater x y | x > y = true greater _ _ = false 7.7. Record Patterns 25 PureScript Documentation, Release 0.5.0 26 Chapter 7. Pattern Matching CHAPTER 8 Modules All code in PureScript is contained in a module. Modules are introduced using the module keyword: module A where id x = x When referencing values or data types in another module, names may be qualified by using a dot: module B where foo = A.id 8.1 Importing Modules A module can be imported using the import keyword. This will create aliases for all of the values and types in the imported module: module B where import A Alternatively, a list of names to import can be provided in parentheses: module B where import A (runFoo) Values, type constructors and data constructors can all be explicitly imported. A type constructor should be followed by a list of associated data constructors to import in parentheses. A double dot (..) can be used to import all data constructors for a given type constructor: module B where import A (runFoo, Foo(..), Bar(Bar)) 8.2 Qualified Imports Modules can also be imported qualified, which means that their names will not be brought directly into scope, but rather, aliased to a different module name. This can be helpful when avoiding naming conflicts: 27 PureScript Documentation, Release 0.5.0 module Main where import qualified Data.Array as A null = ... Here, the name null would ordinarily conflict with null from Data.Array, but the qualified import solves this problem. Data.Array.null can be referenced using A.null instead. 8.3 Module Exports Module exports can be restricted to a set of names by providing that set in parentheses in the module declaration: module A (runFoo, Foo(..)) where The types of names which can be exported is the same as for module imports. 28 Chapter 8. Modules CHAPTER 9 Foreign Function Interface 9.1 Importing Values The foreign import keywords declare a value which is defined in Javascript, and its type: foreign import pow :: Number -> Number -> Number 9.2 Inline Javascript A foreign import declaration may optionally contain its definition in Javascript as a string literal. If this is provided, the string will be inserted directly into the generated Javascript before the current module definition: foreign import pow """function pow(n) { return function(p) { return Math.pow(n, p); }; }""" :: Number -> Number -> Number 9.3 Importing Types To declare a new type with no constructors, use foreign import data and provide the kind: foreign import data DOM :: * foreign import document :: { createElement :: String -> DOM } 9.4 Importing Type Class Instances Type class instances can be imported with foreign import instance: foreign import instance showString :: Prelude.Show String 29 PureScript Documentation, Release 0.5.0 30 Chapter 9. Foreign Function Interface CHAPTER 10 Module Documentation 10.1 Module Prelude 10.1.1 Types data LT GT EQ Ordering where :: Ordering :: Ordering :: Ordering data Unit where Unit :: { } -> Unit 10.1.2 Type Classes Figure 10.1: Prelude class Alternative f where empty :: forall a. f a (<|>) :: forall a. f a -> f a -> f a class (Apply f) <= Applicative f where pure :: forall a. a -> f a class (Functor f) <= Apply f where (<*>) :: forall a b. f (a -> b) -> f a -> f b 31 PureScript Documentation, Release 0.5.0 class (Apply m) <= Bind m where (>>=) :: forall a b. m a -> (a -> m b) -> m b class Bits b where (&) :: b -> b -> b (|) :: b -> b -> b (^) :: b -> b -> b shl :: b -> Number -> b shr :: b -> Number -> b zshr :: b -> Number -> b complement :: b -> b class BoolLike b where (&&) :: b -> b -> b (||) :: b -> b -> b not :: b -> b class (Semigroupoid a) <= Category a where id :: forall t. a t t class Eq a where (==) :: a -> a -> Boolean (/=) :: a -> a -> Boolean class Functor f where (<$>) :: forall a b. (a -> b) -> f a -> f b class (Applicative m, Bind m) <= Monad m where class Num a where (+) :: a -> a -> (-) :: a -> a -> (*) :: a -> a -> (/) :: a -> a -> (%) :: a -> a -> negate :: a -> a a a a a a class (Eq a) <= Ord a where compare :: a -> a -> Ordering class Semigroup a where (<>) :: a -> a -> a class Semigroupoid a where (<<<) :: forall b c d. a c d -> a b c -> a b d class Show a where show :: a -> String 10.1.3 Type Class Instances instance applicativeArr :: Applicative (Prim.Function r) instance applyArr :: Apply (Prim.Function r) instance bindArr :: Bind (Prim.Function r) 32 Chapter 10. Module Documentation PureScript Documentation, Release 0.5.0 instance bitsNumber :: Bits Number instance boolLikeBoolean :: BoolLike Boolean instance categoryArr :: Category Prim.Function instance eqArray :: (Eq a) => Eq [a] instance eqBoolean :: Eq Boolean instance eqNumber :: Eq Number instance eqOrdering :: Eq Ordering instance eqString :: Eq String instance eqUnit :: Eq Unit instance functorArr :: Functor (Prim.Function r) instance monadArr :: Monad (Prim.Function r) instance numNumber :: Num Number instance ordArray :: (Ord a) => Ord [a] instance ordBoolean :: Ord Boolean instance ordNumber :: Ord Number instance ordString :: Ord String instance ordUnit :: Ord Unit instance semigroupArr :: (Semigroup s’) => Semigroup (s -> s’) instance semigroupString :: Semigroup String instance semigroupUnit :: Semigroup Unit instance semigroupoidArr :: Semigroupoid Prim.Function instance showArray :: (Show a) => Show [a] instance showBoolean :: Show Boolean instance showNumber :: Show Number instance showOrdering :: Show Ordering instance showString :: Show String instance showUnit :: Show Unit 10.1. Module Prelude 33 PureScript Documentation, Release 0.5.0 10.1.4 Values (#) :: forall a b. a -> (a -> b) -> b ($) :: forall a b. (a -> b) -> a -> b (++) :: forall s. (Semigroup s) => s -> s -> s (:) :: forall a. a -> [a] -> [a] (<) :: forall a. (Ord a) => a -> a -> Boolean (<=) :: forall a. (Ord a) => a -> a -> Boolean (>) :: forall a. (Ord a) => a -> a -> Boolean (>=) :: forall a. (Ord a) => a -> a -> Boolean (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b asTypeOf :: forall a. a -> a -> a cons :: forall a. a -> [a] -> [a] const :: forall a b. a -> b -> a flip :: forall a b c. (a -> b -> c) -> b -> a -> c liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b refEq :: forall a. a -> a -> Boolean refIneq :: forall a. a -> a -> Boolean return :: forall m a. (Monad m) => a -> m a unit :: Unit void :: forall f a. (Functor f) => f a -> f Unit 10.2 Module Data.Function 10.2.1 Types data Fn0 :: * -> * data Fn1 :: * -> * -> * data Fn10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * data Fn2 :: * -> * -> * -> * 34 Chapter 10. Module Documentation PureScript Documentation, Release 0.5.0 data Fn3 :: * -> * -> * -> * -> * data Fn4 :: * -> * -> * -> * -> * -> * data Fn5 :: * -> * -> * -> * -> * -> * -> * data Fn6 :: * -> * -> * -> * -> * -> * -> * -> * data Fn7 :: * -> * -> * -> * -> * -> * -> * -> * -> * data Fn8 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * data Fn9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * 10.2.2 Values mkFn0 :: forall a. (Unit -> a) -> Fn0 a mkFn1 :: forall a b. (a -> b) -> Fn1 a b mkFn10 :: forall a b c d e f g h i j k. (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k) -> Fn10 mkFn2 :: forall a b c. (a -> b -> c) -> Fn2 a b c mkFn3 :: forall a b c d. (a -> b -> c -> d) -> Fn3 a b c d mkFn4 :: forall a b c d e. (a -> b -> c -> d -> e) -> Fn4 a b c d e mkFn5 :: forall a b c d e f. (a -> b -> c -> d -> e -> f) -> Fn5 a b c d e f mkFn6 :: forall a b c d e f g. (a -> b -> c -> d -> e -> f -> g) -> Fn6 a b c d e f g mkFn7 :: forall a b c d e f g h. (a -> b -> c -> d -> e -> f -> g -> h) -> Fn7 a b c d e f g h mkFn8 :: forall a b c d e f g h i. (a -> b -> c -> d -> e -> f -> g -> h -> i) -> Fn8 a b c d e f g h mkFn9 :: forall a b c d e f g h i j. (a -> b -> c -> d -> e -> f -> g -> h -> i -> j) -> Fn9 a b c d on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c runFn0 :: forall a. Fn0 a -> a runFn1 :: forall a b. Fn1 a b -> a -> b runFn10 :: forall a b c d e f g h i j k. Fn10 a b c d e f g h i j k -> a -> b -> c -> d -> e -> f -> runFn2 :: forall a b c. Fn2 a b c -> a -> b -> c runFn3 :: forall a b c d. Fn3 a b c d -> a -> b -> c -> d runFn4 :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> e runFn5 :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> f runFn6 :: forall a b c d e f g. Fn6 a b c d e f g -> a -> b -> c -> d -> e -> f -> g 10.2. Module Data.Function 35 PureScript Documentation, Release 0.5.0 runFn7 :: forall a b c d e f g h. Fn7 a b c d e f g h -> a -> b -> c -> d -> e -> f -> g -> h runFn8 :: forall a b c d e f g h i. Fn8 a b c d e f g h i -> a -> b -> c -> d -> e -> f -> g -> h -> runFn9 :: forall a b c d e f g h i j. Fn9 a b c d e f g h i j -> a -> b -> c -> d -> e -> f -> g -> h 10.3 Module Data.Eq 10.3.1 Types data Ref a where Ref :: a -> Ref a 10.3.2 Type Class Instances instance eqRef :: Eq (Ref a) instance functorRef :: Functor Ref 10.3.3 Values liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b 10.4 Module Prelude.Unsafe 10.4.1 Values unsafeIndex :: forall a. [a] -> Number -> a 10.5 Module Control.Monad.Eff 10.5.1 Types data Eff :: # ! -> * -> * type Pure a = forall e. Eff e a 10.5.2 Type Class Instances instance applicativeEff :: Applicative (Eff e) instance applyEff :: Apply (Eff e) instance bindEff :: Bind (Eff e) 36 Chapter 10. Module Documentation PureScript Documentation, Release 0.5.0 instance functorEff :: Functor (Eff e) instance monadEff :: Monad (Eff e) 10.5.3 Values bindE :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b forE :: forall e. Number -> Number -> (Number -> Eff e Unit) -> Eff e Unit foreachE :: forall e a. [a] -> (a -> Eff e Unit) -> Eff e Unit returnE :: forall e a. a -> Eff e a runPure :: forall a. Pure a -> a untilE :: forall e. Eff e Boolean -> Eff e Unit whileE :: forall e a. Eff e Boolean -> Eff e a -> Eff e Unit 10.6 Module Control.Monad.Eff.Unsafe 10.6.1 Values unsafeInterleaveEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a 10.7 Module Debug.Trace 10.7.1 Types data Trace :: ! 10.7.2 Values print :: forall a r. (Show a) => a -> Eff (trace :: Trace | r) Unit trace :: forall r. String -> Eff (trace :: Trace | r) Unit 10.8 Module Control.Monad.ST 10.8.1 Types 10.6. Module Control.Monad.Eff.Unsafe 37 PureScript Documentation, Release 0.5.0 data ST :: * -> ! data STArray :: * -> * -> * data STRef :: * -> * -> * 10.8.2 Values modifySTRef :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a newSTArray :: forall a h r. Number -> a -> Eff (st :: ST h | r) (STArray h a) newSTRef :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a) peekSTArray :: forall a h r. STArray h a -> Number -> Eff (st :: ST h | r) a pokeSTArray :: forall a h r. STArray h a -> Number -> a -> Eff (st :: ST h | r) a readSTRef :: forall a h r. STRef h a -> Eff (st :: ST h | r) a runST :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a runSTArray :: forall a r. (forall h. Eff (st :: ST h | r) (STArray h a)) -> Eff r [a] writeSTRef :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a 38 Chapter 10. Module Documentation CHAPTER 11 Indices and tables • genindex • modindex • search 39