{"id":22571223,"url":"https://github.com/mjepronk/wiwinwl-purescript","last_synced_at":"2026-03-15T13:50:18.156Z","repository":{"id":133128849,"uuid":"114234392","full_name":"mjepronk/wiwinwl-purescript","owner":"mjepronk","description":"What I Wish I Knew When Learning PureScript","archived":false,"fork":false,"pushed_at":"2020-10-19T16:59:49.000Z","size":13,"stargazers_count":108,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-15T02:43:46.688Z","etag":null,"topics":["purescript"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mjepronk.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-14T10:06:45.000Z","updated_at":"2024-09-25T08:16:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"0c8b5393-c67f-425d-962d-bfbaae98bcf6","html_url":"https://github.com/mjepronk/wiwinwl-purescript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mjepronk/wiwinwl-purescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjepronk%2Fwiwinwl-purescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjepronk%2Fwiwinwl-purescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjepronk%2Fwiwinwl-purescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjepronk%2Fwiwinwl-purescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mjepronk","download_url":"https://codeload.github.com/mjepronk/wiwinwl-purescript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjepronk%2Fwiwinwl-purescript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272828809,"owners_count":25000091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["purescript"],"created_at":"2024-12-08T01:15:56.905Z","updated_at":"2026-03-15T13:50:13.108Z","avatar_url":"https://github.com/mjepronk.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":":toc: macro\n:toc-title:\n:toclevels: 99\n\n# What I Wish I Knew When Learning PureScript\n\n[IMPORTANT]\n====\nThis documentation can be outdated. See \u003c\u003cLinks\u003e\u003e for official documentation.\n====\n\nA concise overview of the PureScript language and ecosystem, in the same style\nas http://dev.stephendiehl.com/hask/[\"What I Wish I Knew When Learning\nHaskell\"] by Stephen Diehl.\n\n## Table of Contents\ntoc::[]\n\n## Basics\n\n### Install PureScript and Spago\n\nWe will use NPM to install PureScript. If you want to install PureScript (and\nother NPM packages) into your home directory (rather than to the global system\ndirectories), you could set a `prefix` in your `npmrc`. On Linux you can do:\n\n```bash\n$ npm set prefix $HOME/.local\n```\n\nThen the following commands can be run as an ordinary user instead of as root:\n\n```bash\n$ npm install -g purescript@0.13.x spago\n```\n\nWe only need to create a symlink to `purs.bin`. If you installed to the\n`$HOME/.local` prefix then you can do it as follows. Also, make sure that\n`$HOME/.local/bin/` is in your path.\n\n```bash\n$ export PATH=\"$HOME/.local/bin/:$PATH\"\n$ cd ~/.local/bin/\n$ ln -s ../lib/node_modules/purescript/purs.bin purs\n$ purs --version\n0.13.8\n```\n\n```bash\n$ spago version\n0.16.0\n```\n\nIf you get something like the following error:\n\n```\nspago: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory\n```\n\nI solved it on Fedora by installing the package `ncurses-compat-libs`. You could\nalso https://github.com/spacchetti/spago/issues/104#issue-408423391[create a\nsymlink] or install from source.\n\n### Starting a new project with Spago\n\nNow we can use https://github.com/spacchetti/spago[Spago] (a package manager and\nbuild tool for PureScript) to create a new empty project.\n\n```bash\n$ mkdir purescript-hello\n$ cd purescript-hello/\n$ spago init\n```\n\nWe are going to use it to install some additional dependencies. Do not include\nthe `purescript-` prefix of the package when using Spago, so for example to\ninstall `purescript-maybe`:\n\n```bash\n$ spago install maybe\n```\n\nSpago adds the dependency to your project configuration file (`spago.dhall`). As\nthe extension implies this is a file written in the Dhall configuration language\n(see this https://github.com/dhall-lang/dhall-lang/wiki/Cheatsheet[cheatsheet]).\n\nSpago uses https://github.com/purescript/package-sets[package sets] to ensure\nthat all the libraries can be build together because there is only one version\nof each.\n\nNOTE: You may need to\nhttps://github.com/spacchetti/spago#add-a-package-to-the-package-set[add\nPureScript libraries to your local package set] if they are on Bower but not\npart of the package set.\n\n### Run\n\nRun your code with `spago run`:\n\n```bash\n$ spago run\n[..snip..]\n[info] Build succeeded.\n🍝\n```\n\n### PSCi\n\nPSCi is the REPL for PureScript, you can use Spago to run it for you:\n\n```bash\n$ spago repl\n```\n\nImporting modules on the REPL uses the same syntax as in the source code. In\nPSCi you do not use `let` to bind variables (as of version 0.11). So, you can\nwrite:\n\n```purescript\n\u003e import Data.Maybe\n\u003e foo = Just 1\n```\n\nIf you try to reassign an existing binding PSCi will complain. You either have\nto chose a new variable name or you can optionally `:reload`. Which will remove\nall bindings and reimports all your imported modules (compiling when necessary).\n\nYou can see the type of an expression with `:t` (or `:type`):\n\n```purescript\n\u003e :t Just 1\nMaybe Int\n```\n\nAnother handy feature is `:paste` mode, which allows you to paste multiple lines\nof code into PSCi, or to type a statement with multiple lines. You can finish\ninput by pressing `Ctrl-D` while on the last empty line.\n\n### Documentation\n\nYou can build documentation for your project and all it's dependencies in HTML\nformat like so:\n\n```bash\n$ spago docs --open\n```\n\nThis can be really useful when you don't have continuous Internet access (and\nthus access to Pursuit).\n\n## Types\n\nThe built-in types are defined in the\nhttps://pursuit.purescript.org/builtins/docs/Prim[Prim] module that is\nembedded in the PureScript compiler (this module is implicitly imported in every\nmodule).\n\n### Number\n\nA double precision floating point number (IEEE 754).\n\n```purescript\n\u003e :t 42.0\nNumber\n```\n\nTODO: show all operators that work with Number\n\n### Int\n\nA 32-bit signed integer.\n\n```purescript\n\u003e :t 42\nInt\n```\n\nYou can also use hexadecimal notation for Integer literals:\n\n```purescript\n\u003e 0xff\n255\n\n\u003e :t 0xff\nInt\n```\n\nNOTE: Note that you can't mix `Int` and `Number` in expressions like `add` and\n`div`. Use `toNumber` from `Data.Int` (package `purescript-integers`) to convert\nan `Int` to a `Number`.\n\n### String\n\nStrings are a built-in type in PureScript and correspond to the native string in\nJavaScript. So, unlike Haskell they're not stored as a list of characters.\n\n```purescript\n\u003e :t \"Hello world!\"\nString\n```\n\nMulti-line string literals are also supported with triple quotes (\"\"\"):\n\n```purescript\n\u003e :paste  -- paste mode allows us to type multi-line statements in PSCi\n\u003e multiline = \"\"\"Hello\n… world!\"\"\"\n…  -- press Ctrl-D now to stop paste mode\n\u003e multiline\n\"Hello\\nworld!\"\n```\n\nString utility functions can be found in\nhttps://github.com/purescript/purescript-strings[`purescript-strings`]. It\nalso contains functions for the `Char` type.\n\n### Char\n\nA single character (UTF-16 code unit). The JavaScript representation is a normal\nString, which is guaranteed by the PureScript type system to contain one code\nunit.\n\n```purescript\n\u003e :t 'a'\nChar\n```\n\n### Boolean\n\nEither `true` or `false`.\n\nNOTE: Note that the values are written in lowercase like in JavaScript, in\ncontrast with Haskell where they are written capitalized. Also, the type is\ncalled `Boolean` instead of `Bool` as in Haskell.\n\n```purescript\n\u003e true == false  -- equal\nfalse\n\n\u003e true /= false  -- not equal\ntrue\n\n\u003e true || false  -- or\ntrue\n\n\u003e true \u0026\u0026 false  -- and\nfalse\n\n\u003e not true       -- negation\nfalse\n```\n\n### Array\n\nArrays are implemented using Javascript arrays, but must be homogeneous (all\nelements must be of the same type). They support efficient random access. The\n`Data.Array` module from\nhttps://github.com/purescript/purescript-arrays[`purescript-arrays`] provides\nmany functions for working with arrays.\n\n```purescript\n\u003e import Data.Array\n\u003e xs = [1, 2, 3, 4, 5]\n\u003e :t xs\nArray Int\n\u003e head xs  -- head is a total function in PS\nJust 1\n```\n\nNOTE: you cannot pattern match on arrays as you can in Haskell with lists.\n\n### Records\n\nRecords correspond to JavaScript's objects, and record literals (values) have the same\nsyntax as JavaScript's object literals:\n\n```purescript\n\u003e lang = { title: \"PureScript\", strictEval: true, pure: true }\n\u003e lang.title\n\"PureScript\"\n```\n\n#### Pattern matching\n\nWe can perform pattern matching on records like this:\n\nTODO\n\n#### Record puns\n\nThe functionality `{..}` does not exist in PS?\n\nNOTE: These are sometimes called object puns\n\n#### Polymorphic records\n\nTODO\n\n### List\n\nLinked lists are not a built-in type in PureScript, but are provided by the\nlibrary https://github.com/purescript/purescript-lists[`purescript-lists`].\nThere are lazy and strict versions available.\n\n```purescript\nimport Data.List (List(..), (:), fromFoldable, range)\n\nsomeList :: List Int\nsomeList = 1 : 2 : 3 : Nil\n\nlistFromArray :: List Int\nlistFromArray = fromFoldable [1, 2, 3]\n\nlistUsingRange :: List Int\nlistUsingRange = range 1 3\n```\n\nNOTE: There is no special syntax to write the type of a list (i.e. `[String]` or\n`[Int]` as in Haskell), it's just `List String`.\n\n### Unit\n\nPureScript has a type `Unit` used in place of Haskell's `()`. The Prelude module\nprovides a value `unit` that inhabits this type.\n\n## Modules\n\n### Defining a module\n\nA source file must contain exactly one module. A module declaration looks like\nthis:\n\n```purescript\nmodule Main where\n\nimport Prelude\n```\n\nModule names do not need to match the filename, but it's\nrecommended. Module names should be unique within a project.\n\n### Prelude\n\nIn PureScript the Prelude libraries are not bundled with the compiler. You need\nto install the `purescript-prelude` library. Also, the prelude is not imported\nautomatically, just add the following line to the top of your module.\n\n```purescript\nimport Prelude\n```\n\n### Main\n\nThe function `main` in the module with the name `Main` is the entry point of a\nscript.\n\n```purescript\nmodule Main where\n\nimport Effect.Console (log)\n\nmain :: Effect Unit\nmain = log \"Hello world!\"\n```\n\nAs you can see here in the type of `main`, PureScript has a type `Unit` used in\nplace of Haskell's `()`. The Prelude module provides a value `unit` that\ninhabits this type.\n\n### Importing modules\n\nImports must appear before other declarations in a module.\n\nTo open import a module:\n\n```purescript\nimport Prelude\n```\n\nPureScript allows one open import per module. Usually this is `Prelude`.\n\nTo import a specific set of members:\n```purescript\nimport Prelude (head, tail)\n```\n\nImport one data constructor of a given type constructor:\n```purescript\nimport Data.Maybe (Maybe(Just))\n```\n\nImporting all data constructors for a given type constructor:\n```purescript\nimport Data.Maybe (Maybe(..))\n```\n\nImporting type classes:\n```purescript\nimport Prelude (class Show)\n```\n\nImporting qualified:\n```purescript\nimport Data.Maybe as Data.Maybe\n```\n\nNOTE: Note that PureScript does not have the `qualified` keyword as Haskell. An\nimport is always qualified with `as`.\n\nOnly names that have been imported into a module can be referenced, and you can\nonly reference things exactly as you imported them.\n\nSome examples:\n\n|===\n|Import statement |Exposed members\n\n|`import X`\n|`A`, `f`\n\n|`import X as Y`\n| `Y.A`, `Y.f`\n\n|`import X (A)`\n| `A`\n\n|`import X (A) as Y`\n| `Y.A`\n\n|`import X hiding (f)`\n| `A`\n\n|`import Y hiding (f) as Y`\n| `Y.A`\n|===\n\n### Exporting modules\n\nExport only a set of it's members:\n```purescript\nmodule A (runFoo, Foo(..)) where\n```\n\nExport a type class:\n```purescript\nmodule A (class B) where\n```\n\nRe-export a module in it's entirety:\n```purescript\nmodule A (module B) where\nimport B\n```\n\nRe-export the module itself in it's entirety:\n```purescript\nmodule A (module A, module B) where\nimport B\ndata ...\n```\n\nRe-export a restricted set of members:\n```purescript\nmodule A (module ExportB) where\nimport B (foo, bar) as ExportB\n```\n\n\n## Functions\n\n### Function composition\n\nIn PureScript function composition is done with the `(\u003c\u003c\u003c)` operator:\n\n```purescript\n\n\u003e import Data.String (toLower, trim)\n\u003e clean = toLower \u003c\u003c\u003c trim\n\u003e clean \" Matthias \"\n\"matthias\"\n\n```\n\n### Operator Sections\n\nPureScript, like Haskell, supports operator sections, or partial application on\ninfix operators, however the syntax is different: you need to put an underscore\nin the place of the newly created function's argument. For example:\n\n```purescript\n\n\u003e import Data.Array ((..))  -- Import the `range` operator from Data.Array\n\u003e map (2 * _) (1..10)\n[2,4,6,8,10,12,14,16,18,20]\n\n\u003e prependHello = (\"Hello \" \u003c\u003e _)\n\u003e prependHello \"World\"\n\"Hello World\"\n\n\u003e (_ \u003c\u003e \"!\") (prependHello \"World\")\n\"Hello World!\"\n\n```\n\n## Typeclasses\n\n### Create a type class\n\nWe can define a type class using the `class` keyword:\n\n```purescript\n\nclass Show a where\n  show :: a -\u003e String\n\n```\n\n### Create an instance\n\nWe can manually create an instance for a type class like this:\n\n```purescript\n\ndata Colour = Red | White | Blue\n\ninstance eqColour :: Eq Colour where\n  eq Red   Red   = true\n  eq White White = true\n  eq Blue  Blue  = true\n  eq _     _     = false\n\ninstance showColour :: Show Colour where\n  show Red   = \"Red\"\n  show White = \"White\"\n  show Blue  = \"Blue\"\n\n```\n\n### Instance deriving\n\nOf course this may become tedious, that's why the PureScript compiler supports\nautomatic deriving for a number of type classes:\n\n```purescript\n\ndata Colour = Red | White | Blue\n\nderive instance eqColour :: Eq Colour\n```\n\nCurrently, the following type classes can be automatically derived by the\ncompiler:\n\n- Data.Eq (class Eq)\n- Data.Ord (class Ord)\n- Data.Functor (class Functor)\n- Data.Newtype (class Newtype)\n- Data.Generic.Rep (class Generic)\n\n### Newtype deriving\n\nIn Haskell it's common to define a newtype using record syntax to automatically\ncreate an unwrap function. In PureScript the `Newtype` type class provides\n`unwrap`. The compiler can derive instances of `Newtype` automatically:\n\n```purescript\n\nnewtype EmailAddress = EmailAddress String\n\nderive instance newtypeEmailAddress :: Newtype EmailAddress _\n\nmain = do\n  let email = EmailAddress \"me@example.com\"\n  log $ unwrap email\n```\n\nThis requires the `purescript-newtype` package.\n\n### Generic deriving\n\nGeneric deriving allows data-type generic programming (inspired by GHC's\nGenerics). This technique allows us for example to easily create\nserialization/deserialization code for our own data types (as done by Argonaut).\nThe basic functionality is provided by the `purescript-generics-rep` package.\n\nFor example we can use a function `genericShow` that works on all\ntypes that have an instance for the `Generic` typeclass:\n\n```purescript\nimport Data.Generic.Rep (class Generic)\nimport Data.Generic.Rep.Show (genericShow)\n\ndata Colour = Red | White | Blue\n\nderive instance genericColour :: Generic Colour _\n\ninstance showColour :: Show Colour where\n  show = genericShow\n```\n\n### Deriving instances for records\n\nIf you want to create instances for records, you need to wrap the record in a\nnewtype first (or use `data` to declare your type). Like this:\n\n```purescript\nimport Prelude\nimport Data.Generic.Rep (class Generic)\nimport Data.Generic.Rep.Eq (genericEq)\nimport Data.Generic.Rep.Show (genericShow)\nimport Data.Generic.Rep.Ord (genericCompare)\n\nnewtype Person = Person { firstName :: String, lastName :: String }\n\nderive instance genericPerson :: Generic Person _\n\n-- This is equivalent to:\n-- `derive instance eqPerson :: Eq Person`\ninstance eqPerson :: Eq Person where\n  eq = genericEq\n\n-- This is equivalent to:\n-- `derive instance ordPerson :: Ord Person`\ninstance ordPerson :: Ord Person where\n  compare = genericCompare\n\ninstance showPerson :: Show Person where\n  show = genericShow\n```\n\n## Common type classes\n\n### Relationships\n\nimage::http://g.gravizo.com/g?digraph%20G%20{%22Semigroupoid%22%20-%3E%20%22Category%22%22Functor%22%20-%3E%20%22Apply%22%22Apply%22%20-%3E%20%22Applicative%22%22Semigroup%22%20-%3E%20%22Monoid%22%22Monoid%22%20-%3E%20%22Foldable%22%20[style=dotted]%22Functor%22%20-%3E%20%22Traversable%22%22Foldable%22%20-%3E%20%22Traversable%22%22Applicative%22%20-%3E%20%22Traversable%22%20[style=dotted]%22Applicative%22%20-%3E%20%22Monad%22%22Apply%22%20-%3E%20%22Bind%22%22Bind%22%20-%3E%20%22Monad%22}[Type class hierarchy]\n\n////\nhttp://g.gravizo.com/g?\n  digraph G {\n    \"Semigroupoid\" -\u003e \"Category\"\n    \"Functor\" -\u003e \"Apply\"\n    \"Apply\" -\u003e \"Applicative\"\n    \"Semigroup\" -\u003e \"Monoid\"\n    \"Monoid\" -\u003e \"Foldable\" [style=dotted]\n    \"Functor\" -\u003e \"Traversable\"\n    \"Foldable\" -\u003e \"Traversable\"\n    \"Applicative\" -\u003e \"Traversable\" [style=dotted]\n    \"Applicative\" -\u003e \"Monad\"\n    \"Apply\" -\u003e \"Bind\"\n    \"Bind\" -\u003e \"Monad\"\n  }\n)\n////\n\n\n### Semigroupoid *(purescript-prelude)*\n\nA Semigroupoid is similar to a Category but does not require an identity\nelement, just composable https://github.com/hemanth/functional-programming-jargon#morphism[morphisms].\n\n```purescript\nclass Semigroupoid a where\n  compose :: forall b c d. a c d -\u003e a b c -\u003e a b d\n```\n\nNOTE: `(\u003c\u003c\u003c)` is an alias for `compose`. `(\u003e\u003e\u003e)` is an alias for `flip compose`.\nSo, function composition is done with the `(\u003c\u003c\u003c)` operator unlike `(.)` in\nHaskell. The `.` is used for record field access in PureScript.\n\n### Category *(purescript-prelude)*\n\n`Category`s consist of objects and composable morphisms between them, and as\nsuch are `Semigroupoid`s, but unlike `Semigroupoid`s must have an identity\nelement.\n\n```purescript\nclass (Semigroupoid a) \u003c= Category a where\n  identity :: forall t. a t t\n```\n\nNOTE: Per version 4.0.0 of the Prelude `id` has been renamed to `identity`.\n\n### Semigroup *(purescript-prelude)*\n\nThe Semigroup type class identifies those types which support an append\noperation to combine two values.\n\n```purescript\nclass Semigroup a where\n  append :: a -\u003e a -\u003e a\n```\n\nNOTE: `(\u003c\u003e)` is an alias for `append`. The `(++)` operator as an alias for\n`append` is removed in PureScript 0.9.1.\n\n### Monoid *(purescript-monoid)*\n\nThe `Monoid` type class extends the `Semigroup` type class with the concept of\nan empty value, called `mempty`.\n\n```purescript\nclass Semigroup m \u003c= Monoid m where\n  mempty :: m\n```\n\n### Functor *(purescript-prelude)*\n\nThe map function allows a function to be “lifted” over a data structure.\n\n```purescript\nclass Functor f where\n  map :: forall a b. (a -\u003e b) -\u003e f a -\u003e f b\n```\n\nNOTE: `(\u003c$\u003e)` is an alias for `map`. `(\u003c#\u003e)` is an alias for `map` with its\narguments reversed.\nNOTE: PureScript uses `map` instead of Haskell's `fmap`.\n\n### Foldable *(purescript-foldable-traversable)*\n\nIf the `Monoid` type class identifies those types which act as the result of a\nfold, then the `Foldable` type class identifies those type constructors which\ncan be used as the source of a fold.\n\n```purescript\nclass Foldable f where\n  foldr :: forall a b. (a -\u003e b -\u003e b) -\u003e b -\u003e f a -\u003e b\n  foldl :: forall a b. (b -\u003e a -\u003e b) -\u003e b -\u003e f a -\u003e b\n  foldMap :: forall a m. Monoid m =\u003e (a -\u003e m) -\u003e f a -\u003e m\n```\n\n### Apply *(purescript-prelude)*\n\nThe `Apply` type class is a subclass of `Functor`, and defines an additional\nfunction `apply`. The difference between `map` and `apply` is that `map` takes a\nfunction as an argument, whereas the first argument to `apply` is wrapped in the\ntype constructor `f`.\n\n```purescript\nclass Functor f \u003c= Apply f where\n  apply :: forall a b. f (a -\u003e b) -\u003e f a -\u003e f b\n```\n\nNOTE: `(\u003c*\u003e)` is an alias for `apply`.\n\n### Applicative *(purescript-prelude)*\n\nApplicative is a subclass of `Apply` and defines the `pure` function. `pure`\ntakes a value and returns a value whose type has been wrapped with the type\nconstructor `f`.\n\n```purescript\nclass Apply f \u003c= Applicative f where\n  pure :: forall a. a -\u003e f a\n```\n\n### Traversable *(purescript-foldable-traversable)*\n\nA traversable functor provides the ability to combine a collection of\nside-effects which depend on its structure.\n\n```purescript\nclass (Functor t, Foldable t) \u003c= Traversable t where\n  traverse :: forall a b f. Applicative f =\u003e (a -\u003e f b) -\u003e t a -\u003e f (t b)\n  sequence :: forall a f. Applicative f =\u003e t (f a) -\u003e f (t a)\n```\n\n### Monad *(purescript-prelude)*\n\n```purescript\nclass Apply m \u003c= Bind m where\n  bind :: forall a b. m a -\u003e (a -\u003e m b) -\u003e m b\n\nclass (Applicative m, Bind m) \u003c= Monad m\n```\n\nNOTE: `(\u003e\u003e=)` is an alias for `bind`. PureScript does not have `return` as\nan alias for `pure`.\n\n\n## Function types\n\n### Function application\n\n```purescript\n($)   :: forall a b.                    (a -\u003e b) -\u003e   a -\u003e   b\n(\u003c$\u003e) :: forall a b f. (Functor f) =\u003e   (a -\u003e b) -\u003e f a -\u003e f b\n(\u003c*\u003e) :: forall a b f. (Apply f)   =\u003e f (a -\u003e b) -\u003e f a -\u003e f b\n(=\u003c\u003c) :: forall m a b. (Bind m)    =\u003e (a -\u003e m b) -\u003e m a -\u003e m b\n(\u003e\u003e=) :: forall a b m. (Bind m)    =\u003e m a -\u003e (a -\u003e m b) -\u003e m b\ntraverse :: forall a b m t. (Traversable t, Applicative m) =\u003e (a -\u003e m b) -\u003e t a -\u003e m (t b)\nfoldMap  :: forall a m f.   (Foldable f, Monoid m)         =\u003e (a -\u003e m)   -\u003e f a -\u003e m\n```\n\nNOTE: In PureScript `map` can be used instead of `liftA` or `liftM` in Haskell,\nand `traverse` replaces `mapM`.\n\n### Composition\n\n```purescript\n(\u003c\u003c\u003c) :: forall b c d a. (Semigroupoid a) =\u003e a c d -\u003e a b c -\u003e a b d\n(\u003e\u003e\u003e) :: forall a b c d. (Semigroupoid a) =\u003e a b c -\u003e a c d -\u003e a b d\n(\u003c=\u003c) :: forall a b c m. (Bind m) =\u003e (b -\u003e m c) -\u003e (a -\u003e m b) -\u003e a -\u003e m c\n(\u003e=\u003e) :: forall a b c m. (Bind m) =\u003e (a -\u003e m b) -\u003e (b -\u003e m c) -\u003e a -\u003e m c\n```\n\n### Discarding one of two values\n\n```purescript\nconst :: forall a b.                    a -\u003e   b -\u003e   a\n(\u003c$)  :: forall f a b. (Functor f) =\u003e   a -\u003e f b -\u003e f a\n($\u003e)  :: forall f a b. (Functor f) =\u003e f a -\u003e   b -\u003e f b\n(\u003c*)  :: forall a b f. (Apply f)   =\u003e f a -\u003e f b -\u003e f a\n(*\u003e)  :: forall a b f. (Apply f)   =\u003e f a -\u003e f b -\u003e f b\n```\n\nNOTE: Purescript does not have the operators `(\u003e\u003e)` or `(\u003c\u003c)` as `Apply` is a\nsuperclass of `Monad` (i.e. use `(\\*\u003e)` and `(\u003c*)` respectively).\n\n### Restructuring\n\n```purescript\nsequence :: forall a m t. (Traversable t, Applicative m) =\u003e t (m a) -\u003e m (t a)\njoin     :: forall a m.   (Bind m)                       =\u003e m (m a) -\u003e m a\n```\n\n### Identity\n```purescript\nidentity :: forall t a. (Category a)    =\u003e a t t\npure     :: forall a f. (Applicative f) =\u003e a -\u003e f a\n```\n\n## Links\n\n### Learning Purescript\n- https://leanpub.com/purescript/read[PureScript by Example]\n- https://github.com/adkelley/javascript-to-purescript/blob/master/index.md[Make the Leap from JavaScript to PureScript]\n- https://jordanmartinez.github.io/purescript-jordans-reference-site/[Jordan's PureScript Reference]\n\n### Reference\n- Official https://github.com/purescript/documentation[PureScript documentation]\n- https://github.com/purescript/documentation/tree/master/language[PureScript Language Reference]\n- https://pursuit.purescript.org/[Pursuit] (official package documentation, like Hackage)\n- https://github.com/hemanth/functional-programming-jargon[Functional programming jargon]\n- https://github.com/purescript/documentation/blob/master/language/Differences-from-Haskell.md[PureScript: Differences from Haskell]\n\n### Generics\n- https://harry.garrood.me/blog/write-your-own-generics/[Making full use of PureScript's Generic type class]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjepronk%2Fwiwinwl-purescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjepronk%2Fwiwinwl-purescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjepronk%2Fwiwinwl-purescript/lists"}