@@ -1,17 +1,19 @@
11# 🎷 purescript-lazy-joe 🦥
22
3−A purescript library for these days when you got the blues and are just too lazy to write ffi code.
3+Zero boilerplate ffi for purescript.
44
5−`lazy-joe` let's you ffi your js library without having to write the typical purescript ffi boilerplate.
5+For these days when you got the blues and are just too lazy to write ffi code.
66
77## ToC
88* [Installation](#installation)
9+* [Quickstart](#quickstart)
910* [Usage](#usage)
1011 * [Method chaining](#method-chaining)
11− * [Uncurried](#uncurried)
12− * [Varargs](#varargs)
13− * [Scoped](#scoped)
14− * [Effectful](#effectful)
12+ * [Uncurried functions](#uncurried-functions)
13+ * [Vararg functions](#vararg-functions)
14+ * [Scoped functions](#scoped-functions)
15+ * [Effectful functions](#effectful-functions)
16+ * [`new` constructor](#new-constructor)
1517* [Credits](#credits)
1618
1719## Installation
@@ -20,6 +22,15 @@ A purescript library for these days when you got the blues and are just too lazy
2022spago install lazy-joe
2123```
2224
25+## Quickstart
26+
27+```
28+main :: Effect Unit
29+main = launchAff_ do
30+ { red } <- fromDefault "chalk" -- import a module
31+ log $ red "Red velvet 🎂" -- use a function
32+```
33+
2334## Usage
2435
2536Imagine we want to use the amazing [`chalk`](https://github.com/chalk/chalk) js library for terminal styling in our purescript code.
@@ -55,7 +66,12 @@ You can easily import the `default` export from a module using `fromDefault`. Th
5566
5667### Method chaining
5768
58−In js method chaining is often used. In chalk, you can combine different styles by chaining:
69+In js method chaining is a common pattern. In purescript we can use function application to model this pattern.
70+
71+
72+#### Example
73+
74+In chalk, you can combine different styles by chaining them:
5975
6076```js
6177import chalk from 'chalk';
@@ -75,31 +91,50 @@ Running it will print:
7591
7692.
7793
78−### Uncurried
94+### Uncurried functions
95+
96+js typically uses uncurried functions (e.g. `f(a,b,c) `) instead of curried functions (e.g. `f(a)(b)(c)` ) like purescript. Use `curried` to use the uncurried js function as a curried purescript function:
97+
98+```
99+result = curried myFunc arg1 arg2 arg3
100+```
101+
102+#### Example
79103
80−js typically uses uncurried functions (e.g. `f(a,b,c) `) instead of uncurried functions (e.g. `f(a)(b)(c)` ) like purescript. E.g. we can use the `blue` function as a three-argument uncurried function:
104+E.g. we can use the `blue` function as a three-argument uncurried function:
81105
82106```js
83107console.log(chalk.blue('blue', 'azul', 'blau'));
84108```
85109
86−In purescript functions are curried, so we need to uncurry them using `uncurried`:
110+In purescript functions are curried, so we need to curry them using `curried`:
87111
88112```purescript
89113main :: Effect Unit
90114main = launchAff_ do
91115 { blue } <- fromDefault "chalk"
92116
93− log $ uncurried blue "blue" "azul" "blau"
117+ log $ curried blue "blue" "azul" "blau"
94118```
95119
96120Running it will print:
97121
98122
99123
100−### Varargs
124+### Vararg functions
101125
102−js functions are sometimes designed to be variadic, i.e. to have a variable number of arguments. In fact, the colour methods in `chalk` are variadic methods (as you have seen in the previous example) and you can pass an arbitrary number of arguments:
126+js functions are sometimes designed to be variadic, i.e. to have a variable number of arguments. Use `variadic myModuleOrFunc func` for functions that accept varargs:
127+
128+```purescript
129+let
130+ example1 = variadic func arg1
131+ example1 = variadic func arg1 arg2 arg3
132+ example1 = variadic func [arg1, arg2, arg3, arg4]
133+```
134+
135+#### Eample
136+
137+In fact, the colour methods in `chalk` are variadic methods (as you have seen in the previous example) and you can pass an arbitrary number of arguments:
103138```js
104139console.log(chalk.blue('Hello', 'world!', 'Hola', 'mundo!'));
105140```
@@ -115,23 +150,41 @@ main = launchAff_ do
115150 log $ variadic blue [ "Hello", "world!", "Hola", "mundo!"]
116151```
117152
118−### Scoped
153+### Scoped functions
119154
120−Sometimes js functions don't work in purescript, because they sometimes use `this` internally which fails to resolve in a curried contex. E.g. simply using the `rgb` function from `chalk` as we did before will fail. To make it work again we will need to set the scope for `this` properly. You can use `scoped` to set the scope of a function to the module:
155+Sometimes js functions don't work in purescript, because they internally use `this` which fails to resolve in a curried contex. Use `scoped myModuleOrFunc func` you to make a function scoped:
156+
157+```purescript
158+result <- scoped myModuleOrFunc func arg1 arg2
159+```
160+
161+#### Example
162+
163+Simply using the `rgb` function from `chalk` as we did before will fail because it uses `this` internally. To make it work again we will need to set the scope for the function to the module:
121164
122165```purescript
123166main :: Effect Unit
124167main = launchAff_ do
125168 m@{ rgb } <- fromDefault "chalk"
126169
127− log $ scoped m (uncurried rgb) 129 37 218 # \{ bold } -> bold "PURPLE!!! 🪁"
170+ log $ scoped m (curried rgb) 129 37 218 # \{ bold } -> bold "PURPLE!!! 🪁"
128171```
129172
130173Running it will print:
131174
132175
133176
134−### Effectful
177+### Effectful functions
178+
179+js functions very often cause side-effects (e.g. like printing to the console). Use `effectful` you to catch these side-effects and return `Effect` instead:
180+
181+```purescript
182+let
183+ result :: Effect SomeResult
184+ result = effectful func arg1 arg2
185+```
186+
187+#### Example
135188
136189Let's try another example and install minimalistic http-client `got`:
137190
@@ -158,12 +211,50 @@ Clearly, `post` is an effectful function, as it triggers a promise. So in puresc
158211main :: Effect Unit
159212main = launchAff_ do
160213 { post } <- fromDefault "got"
161− resp <- Promise.toAffE $ effectful (uncurried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
214+ resp <- Promise.toAffE $ effectful (curried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
162215 log resp.json
163216```
164217
165218We import the `post` from `got`. The first thing we need to do is uncurry it, since it receives two arguments, the url and the json record. We then wrap it using `effectful` so that is run in an `Effect`. We can then call the effectful js function `json()` on the resulting `Promise` to get the body, so we can just `bind` (`>>=`) it.
166219
220+### `new` constructor
221+
222+Use `new` to create new objects:
223+
224+```purescript
225+myModule <- fromDefault "my-module"
226+let myObj = new myModule arg1 arg2
227+```
228+
229+#### Example
230+
231+`fuse.js` is a library for fuzzy search. In js you use it by first creating a new `Fuse` object using `new` and passing the data as a list and some options:
232+```js
233+const fuse = new Fuse(list, options);
234+```
235+Then you can search on this object:
236+```js
237+const pattern = "my-search-pattern"
238+fuse.search(pattern)
239+```
240+
241+We first import the default export from `fuse.js` which gives us the class, which we can then pass to `new` to create the `Fuse` object:
242+
243+```purescript
244+fuse <- fromDefault "fuse.js"
245+ let
246+ list =
247+ [ { "title": "Old Man's War", "author": { "firstName": "John", "lastName": "Scalzi" } }
248+ , { "title": "The Lock Artist", "author": { "firstName": "Steve", "lastName": "Hamilton" } }
249+ ]
250+ options =
251+ { keys: [ "title", "author.firstName" ]
252+ }
253+ result :: Array { item :: { title :: String, author :: { firstName :: String, lastName :: String } } } <-
254+ (new fuse list options) # \f@{ search } -> effectful (scoped f search) "eve"
255+
256+ logShow result
257+```
167258
168259## Credits
169260