git.iko.soy/rowtype-yoga/purescript-lazy-joe
on main help sign in
7 files changed+161−135
since splitsnapshots
unifiedsplit
CHANGELOG.md+13 README.md+97−10 bower.json+24 packages.dhall−99 src/Lazy/Joe.purs+24−24 test.dhall+1 test/Main.purs+2−2
CHANGELOG.mdnew file+13
@@ -0,0 +1,13 @@
1+# Changelog
2+
3+
4+## v1.0.0
5+
6+Initial release. Supports:
7+
8+- importing module (defaults)
9+- currying functions
10+- scoping functions to a module or object
11+- effectful functions
12+- variadic functions (varargs)
13+- `new` constructor
README.md+97−10
@@ -6,10 +6,11 @@ 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)
1112 * [Uncurried functions](#uncurried-functions)
12− * [Varargs functions](#vararg-functions)
13+ * [Vararg functions](#vararg-functions)
1314 * [Scoped functions](#scoped-functions)
1415 * [Effectful functions](#effectful-functions)
1516 * [`new` constructor](#new-constructor)
@@ -21,6 +22,15 @@ For these days when you got the blues and are just too lazy to write ffi code.
2122spago install lazy-joe
2223```
2324
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+
2434## Usage
2535
2636Imagine we want to use the amazing [`chalk`](https://github.com/chalk/chalk) js library for terminal styling in our purescript code.
@@ -56,7 +66,12 @@ You can easily import the `default` export from a module using `fromDefault`. Th
5666
5767### Method chaining
5868
59−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:
6075
6176```js
6277import chalk from 'chalk';
@@ -78,20 +93,28 @@ Running it will print:
7893
7994### Uncurried functions
8095
81−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:
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
103+
104+E.g. we can use the `blue` function as a three-argument uncurried function:
82105
83106```js
84107console.log(chalk.blue('blue', 'azul', 'blau'));
85108```
86109
87−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`:
88111
89112```purescript
90113main :: Effect Unit
91114main = launchAff_ do
92115 { blue } <- fromDefault "chalk"
93116
94− log $ uncurried blue "blue" "azul" "blau"
117+ log $ curried blue "blue" "azul" "blau"
95118```
96119
97120Running it will print:
@@ -100,7 +123,18 @@ Running it will print:
100123
101124### Vararg functions
102125
103−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:
104138```js
105139console.log(chalk.blue('Hello', 'world!', 'Hola', 'mundo!'));
106140```
@@ -118,14 +152,22 @@ main = launchAff_ do
118152
119153### Scoped functions
120154
121−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:
122164
123165```purescript
124166main :: Effect Unit
125167main = launchAff_ do
126168 m@{ rgb } <- fromDefault "chalk"
127169
128− log $ scoped m (uncurried rgb) 129 37 218 # \{ bold } -> bold "PURPLE!!! 🪁"
170+ log $ scoped m (curried rgb) 129 37 218 # \{ bold } -> bold "PURPLE!!! 🪁"
129171```
130172
131173Running it will print:
@@ -134,6 +176,16 @@ Running it will print:
134176
135177### Effectful functions
136178
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
188+
137189Let's try another example and install minimalistic http-client `got`:
138190
139191```console
@@ -159,7 +211,7 @@ Clearly, `post` is an effectful function, as it triggers a promise. So in puresc
159211main :: Effect Unit
160212main = launchAff_ do
161213 { post } <- fromDefault "got"
162− 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
163215 log resp.json
164216```
165217
@@ -167,7 +219,42 @@ We import the `post` from `got`. The first thing we need to do is uncurry it, si
167219
168220### `new` constructor
169221
170−TBA
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+```
171258
172259## Credits
173260
bower.jsonnew file+24
@@ -0,0 +1,24 @@
1+{
2+ "name": "purescript-lazy-joe",
3+ "license": [
4+ "MIT-0"
5+ ],
6+ "repository": {
7+ "type": "git",
8+ "url": "https://github.com/sigma-andex/purescript-lazy-joe.git"
9+ },
10+ "ignore": [
11+ "**/.*",
12+ "node_modules",
13+ "bower_components",
14+ "output"
15+ ],
16+ "dependencies": {
17+ "purescript-aff": "^v7.0.0",
18+ "purescript-aff-promise": "^v4.0.0",
19+ "purescript-effect": "^v4.0.0",
20+ "purescript-functions": "^v6.0.0",
21+ "purescript-prelude": "^v6.0.0",
22+ "purescript-unsafe-coerce": "^v6.0.0"
23+ }
24+}
packages.dhall−99
@@ -1,103 +1,4 @@
1−{-
2−Welcome to your new Dhall package-set!
31
4−Below are instructions for how to edit this file for most use
5−cases, so that you don't need to know Dhall to use it.
6−
7−## Use Cases
8−
9−Most will want to do one or both of these options:
10−1. Override/Patch a package's dependency
11−2. Add a package not already in the default package set
12−
13−This file will continue to work whether you use one or both options.
14−Instructions for each option are explained below.
15−
16−### Overriding/Patching a package
17−
18−Purpose:
19−- Change a package's dependency to a newer/older release than the
20− default package set's release
21−- Use your own modified version of some dependency that may
22− include new API, changed API, removed API by
23− using your custom git repo of the library rather than
24− the package set's repo
25−
26−Syntax:
27−where `entityName` is one of the following:
28−- dependencies
29−- repo
30−- version
31−-------------------------------
32−let upstream = --
33−in upstream
34− with packageName.entityName = "new value"
35−-------------------------------
36−
37−Example:
38−-------------------------------
39−let upstream = --
40−in upstream
41− with halogen.version = "master"
42− with halogen.repo = "https://example.com/path/to/git/repo.git"
43−
44− with halogen-vdom.version = "v4.0.0"
45− with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies
46−-------------------------------
47−
48−### Additions
49−
50−Purpose:
51−- Add packages that aren't already included in the default package set
52−
53−Syntax:
54−where `<version>` is:
55−- a tag (i.e. "v4.0.0")
56−- a branch (i.e. "master")
57−- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977")
58−-------------------------------
59−let upstream = --
60−in upstream
61− with new-package-name =
62− { dependencies =
63− [ "dependency1"
64− , "dependency2"
65− ]
66− , repo =
67− "https://example.com/path/to/git/repo.git"
68− , version =
69− "<version>"
70− }
71−-------------------------------
72−
73−Example:
74−-------------------------------
75−let upstream = --
76−in upstream
77− with benchotron =
78− { dependencies =
79− [ "arrays"
80− , "exists"
81− , "profunctor"
82− , "strings"
83− , "quickcheck"
84− , "lcg"
85− , "transformers"
86− , "foldable-traversable"
87− , "exceptions"
88− , "node-fs"
89− , "node-buffer"
90− , "node-readline"
91− , "datetime"
92− , "now"
93− ]
94− , repo =
95− "https://github.com/hdgarrood/purescript-benchotron.git"
96− , version =
97− "v7.0.0"
98− }
99−-------------------------------
100−-}
1012let upstream =
1023 https://github.com/purescript/package-sets/releases/download/psc-0.15.2-20220613/packages.dhall
1034 sha256:99f976d547980055179de2245e428f00212e36acd55d74144eab8ad8bf8570d8
src/Lazy/Joe.purs+24−24
@@ -6,8 +6,8 @@ module Lazy.Joe
66 , new
77 , class Scoped
88 , scoped
9− , class Uncurried
10− , uncurried
9+ , class Curried
10+ , curried
1111 , class Variadic
1212 , variadic
1313 , from
@@ -36,38 +36,38 @@ foreign import fromDefaultImpl :: forall mod. String -> Effect (Promise mod)
3636fromDefault :: forall mod m. MonadAff m => String -> m mod
3737fromDefault = fromDefaultImpl >>> Promise.toAffE >>> liftAff
3838
39−class Uncurried f output | output -> f where
40− uncurried :: f -> output
39+class Curried f output | output -> f where
40+ curried :: f -> output
4141
42−instance Uncurried (Fn5 a b c d e f) (a -> b -> c -> d -> e -> f) where
43− uncurried = runFn5
42+instance Curried (Fn5 a b c d e f) (a -> b -> c -> d -> e -> f) where
43+ curried = runFn5
4444
45−else instance Uncurried (Fn5 a b c d e f) (Fn5 a b c d e f) where
46− uncurried = identity
45+else instance Curried (Fn5 a b c d e f) (Fn5 a b c d e f) where
46+ curried = identity
4747
48−else instance Uncurried (Fn4 a b c d e) (a -> b -> c -> d -> e) where
49− uncurried = runFn4
48+else instance Curried (Fn4 a b c d e) (a -> b -> c -> d -> e) where
49+ curried = runFn4
5050
51−else instance Uncurried (Fn4 a b c d e) (Fn4 a b c d e) where
52− uncurried = identity
51+else instance Curried (Fn4 a b c d e) (Fn4 a b c d e) where
52+ curried = identity
5353
54−else instance Uncurried (Fn3 a b c d) (a -> b -> c -> d) where
55− uncurried = runFn3
54+else instance Curried (Fn3 a b c d) (a -> b -> c -> d) where
55+ curried = runFn3
5656
57−else instance Uncurried (Fn3 a b c d) (Fn3 a b c d) where
58− uncurried = identity
57+else instance Curried (Fn3 a b c d) (Fn3 a b c d) where
58+ curried = identity
5959
60−else instance Uncurried (Fn2 a b c) (a -> b -> c) where
61− uncurried = runFn2
60+else instance Curried (Fn2 a b c) (a -> b -> c) where
61+ curried = runFn2
6262
63−else instance Uncurried (Fn2 a b c) (Fn2 a b c) where
64− uncurried = identity
63+else instance Curried (Fn2 a b c) (Fn2 a b c) where
64+ curried = identity
6565
66−else instance Uncurried (Fn1 a b) (Fn1 a b) where
67− uncurried = identity
66+else instance Curried (Fn1 a b) (Fn1 a b) where
67+ curried = identity
6868
69−else instance Uncurried (Fn1 a b) (a -> b) where
70− uncurried = runFn1
69+else instance Curried (Fn1 a b) (a -> b) where
70+ curried = runFn1
7171
7272
7373foreign import new0 :: forall a. Fn0 a -> a
test.dhall+1
@@ -5,5 +5,6 @@ in conf // {
55 dependencies = conf.dependencies # [
66 , "spec"
77 , "debug"
8+ , "console"
89 ]
910}
test/Main.purs+2−2
@@ -6,7 +6,7 @@ import Control.Promise as Promise
66import Effect (Effect)
77import Effect.Aff (Aff, launchAff_)
88import Effect.Class.Console (log, logShow)
9−import Lazy.Joe (effectful, fromDefault, new, scoped, uncurried, variadic)
9+import Lazy.Joe (effectful, fromDefault, new, scoped, curried, variadic)
1010
1111main :: Effect Unit
1212main = launchAff_ do
@@ -39,7 +39,7 @@ main = launchAff_ do
3939 c >>= log
4040
4141 { post } <- fromDefault "got"
42− resp <- Promise.toAffE $ effectful (uncurried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
42+ resp <- Promise.toAffE $ effectful (curried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
4343 log resp.json
4444
4545 fuse <- fromDefault "fuse.js"