Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 45547d6

Browse files
committed
Bit more documentation.
1 parent 632f603 commit 45547d6

1 file changed

Lines changed: 62 additions & 8 deletions

File tree

README.md

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
# PureScript-Lens
22

33
This started as an indirect port of [@ekmett][@ekmett]'s [lens][lens] library in PureScript.
4-
It has since been broken apart and simplified a bit.
4+
It has since been broken apart and simplified substantially.
55
The core idea is that these are just [van Laarhoven][van Laarhoven] lenses.
66
Read about them as they were called [functional references][functional references].
77
[SPJ][SPJ] gave a brilliant introductory talk about them [here][SPJ-talk].
88
If you're confused, I'd recommend [SPJ][SPJ]'s talk first.
99
[@ekmett][@ekmett] has talked about them many times, [here's one][ekmett-talk].
10-
For more documentation, you should look at [lens][lens].
11-
12-
__Disclaimer:__
13-
Not much is here at the moment, and it's got some problems.
14-
It's mostly just the `Getter` and `Setter` part of [lens][lens].
15-
The more basic examples work. But, not expect the full expressivity of the actual [lens][lens] library.
10+
For more documentation, you should look at [lens][lens] and any of the lens resources online.
1611

1712
## Installation
1813

@@ -26,9 +21,11 @@ to install it.
2621

2722
## Usage
2823

29-
You *should* be able to import just `Optic.Lens` and have most of what you need. See each directory for a summary of the available functions.
24+
You *should* be able to import just `Optic.Lens` and have most of what you need.
25+
See each directory for a summary of the available functions.
3026

3127
There is no TemplateHaskell like syntax so you must define each lens individually.
28+
Or make use of [purescript-refractor][purescript-refractor], which has predefined lenses and prisms.
3229

3330
----------
3431

@@ -81,6 +78,63 @@ foo = lens (\o -> o.foo) (\o x -> o{foo = x})
8178

8279
This type and implementation states that the function `foo` is a `Lens` from any record with at least a `foo` field of type `a` to any record with at least a `foo` field of type `b`.
8380

81+
So, what are the type synonyms? Some examples are:
82+
83+
```purescript
84+
type Lens s t a b = forall f. (Functor f) => (a -> f b) -> s -> f t
85+
type LensP s a = Lens s s a a
86+
87+
type Prism s t a b = forall f p. (Applicative f, Choice p) => p a (f b) -> p s (f t)
88+
type PrismP s a = Prism s s a a
89+
```
90+
91+
These might seem scary, especially `Prism`, but if you squint at them properly, they look very familiar.
92+
93+
Let's take `Lens`, for example, and instantiate `s = [a], t = [b]`.
94+
95+
Then we have some type: `forall f. (Functor f) => (a -> f b) -> [a] -> f [b]`.
96+
97+
Looks pretty close to `map` (from `Data.Array`).
98+
In fact, if we instantiate the `Functor` with `Identity`,
99+
we get the type isomorphic to `map`: `(a -> Identity b) -> [a] -> Identity [b]`.
100+
101+
With some simple unwrapping, we actually have the type of `map`.
102+
103+
What about `Prism`?
104+
105+
Let's instantiate the `Choice` to `(->)`:
106+
`type Prism s t a b = forall f. (Applicative f) => (a -> f b) -> s -> f t`
107+
This looks pretty close to `traverse`.
108+
109+
So, there's a bunch of similarities to the `Functor` hierarchy, and that's one of the points of this library.
110+
What these types synonyms allow is the ability to use similar idioms that work in the `Functor` hierarchy on containers that are not polymorphic in one variable.
111+
112+
An example of this is if you have some type: `data Foo = Foo Number`.
113+
There's no way to define a `Functor` instance for `Foo`,
114+
so you cannot use `(<$>), (<*>), (>>=), (=>>), pure, extract` and friends.
115+
But, it should be easy to see that it would be trivial to "map" over the `Number` contained within a `Foo`.
116+
117+
If you can define a lens for `Foo`, you can do just that
118+
119+
```purescript
120+
module Foo where
121+
122+
import Optic.Core ((*~), LensP())
123+
124+
data Foo = Foo Number
125+
126+
_Foo :: LensP Foo Number -- forall f. (Functor f) => (Number -> f Number) -> Foo -> f Foo
127+
_Foo f (Foo n) = Foo <$> f n
128+
129+
doubleFoo :: Foo -> Foo
130+
doubleFoo = _Foo *~ 2
131+
```
132+
133+
Now, this is not necessarily the least verbose option for such a trivial example,
134+
but it is definitely one of the more general options.
135+
We were able to reuse plain old functions.
136+
If we have some deeply nested structure, it is much less verbose for that situation.
137+
84138
## Examples
85139

86140
N.B. `(..)` is `(<<<)` purely for aesthetic reasons.

0 commit comments

Comments
 (0)