Skip to content

Commit 1e99a3e

Browse files
committed
Merge pull request #11 from born2defy/DocDumbDown
Function examples of Strong and Choice for approachability
2 parents 933a71c + 346ed68 commit 1e99a3e

6 files changed

Lines changed: 130 additions & 6 deletions

File tree

docs/Data/Profunctor.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,3 @@ arr :: forall a b p. (Category p, Profunctor p) => (a -> b) -> p a b
5252
```
5353

5454
Lift a pure function into any `Profunctor` which is also a `Category`.
55-
56-

docs/Data/Profunctor/Choice.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ sum types.
1414
`left` and `right` lift values in a `Profunctor` to act on the `Left` and
1515
`Right` components of a sum, respectively.
1616

17+
Looking at `Choice` through the intuition of inputs and outputs
18+
yields the following type signature:
19+
```
20+
left :: forall input output a. p input output -> p (Either input a) (Either output a)
21+
right :: forall input output a. p input output -> p (Either a input) (Either a output)
22+
```
23+
If we specialize the profunctor `p` to the `function` arrow, we get the following type
24+
signatures:
25+
```
26+
left :: forall input output a. (input -> output) -> (Either input a) -> (Either output a)
27+
right :: forall input output a. (input -> output) -> (Either a input) -> (Either a output)
28+
```
29+
When the `profunctor` is `Function` application, `left` allows you to map a function over the
30+
left side of an `Either`, and `right` maps it over the right side (same as `map` would do).
31+
1732
##### Instances
1833
``` purescript
1934
instance choiceFn :: Choice Function
@@ -30,6 +45,14 @@ _right-associative / precedence 2_
3045
Compose a value acting on a sum from two values, each acting on one of
3146
the components of the sum.
3247

48+
Specializing `(+++)` to function application would look like this:
49+
```
50+
(+++) :: forall a b c d. (a -> b) -> (c -> d) -> (Either a c) -> (Either b d)
51+
```
52+
We take two functions, `f` and `g`, and we transform them into a single function which
53+
takes an `Either`and maps `f` over the left side and `g` over the right side. Just like
54+
`bi-map` would do for the `bi-functor` instance of `Either`.
55+
3356
#### `(|||)`
3457

3558
``` purescript
@@ -44,4 +67,13 @@ one side of the sum.
4467
This combinator is useful when assembling values from smaller components,
4568
because it provides a way to support two different types of input.
4669

47-
70+
Specializing `(|||)` to function application would look like this:
71+
```
72+
(|||) :: forall a b c d. (a -> c) -> (b -> c) -> Either a b -> c
73+
```
74+
We take two functions, `f` and `g`, which both return the same type `c` and we transform them into a
75+
single function which takes an `Either` value with the parameter type of `f` on the left side and
76+
the parameter type of `g` on the right side. The function then runs either `f` or `g`, depending on
77+
whether the `Either` value is a `Left` or a `Right`.
78+
This allows us to bundle two different computations which both have the same result type into one
79+
function which will run the approriate computation based on the parameter supplied in the `Either` value.

docs/Data/Profunctor/Star.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,3 @@ runStar :: forall f a b. Star f a b -> a -> f b
2323
```
2424

2525
Unwrap a value of type `Star f a b`.
26-
27-

docs/Data/Profunctor/Strong.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ product types.
1414
`first` and `second` lift values in a `Profunctor` to act on the first and
1515
second components of a `Tuple`, respectively.
1616

17+
Another way to think about Strong is to piggyback on the intuition of
18+
inputs and outputs. Rewriting the type signature in this light then yields:
19+
```
20+
first :: forall input output a. p input output -> p (Tuple input a) (Tuple output a)
21+
second :: forall input output a. p input output -> p (Tuple a input) (Tuple a output)
22+
```
23+
If we specialize the profunctor p to the function arrow, we get the following type
24+
signatures, which may look a bit more familiar:
25+
```
26+
first :: forall input output a. (input -> output) -> (Tuple input a) -> (Tuple output a)
27+
second :: forall input output a. (input -> output) -> (Tuple a input) -> (Tuple a output)
28+
```
29+
So, when the `profunctor` is `Function` application, `first` essentially applies your function
30+
to the first element of a `Tuple`, and `second` applies it to the second element (same as `map` would do).
31+
1732
##### Instances
1833
``` purescript
1934
instance strongFn :: Strong Function
@@ -30,6 +45,14 @@ _right-associative / precedence 3_
3045
Compose a value acting on a `Tuple` from two values, each acting on one of
3146
the components of the `Tuple`.
3247

48+
Specializing `(***)` to function application would look like this:
49+
```
50+
(***) :: forall a b c d. (a -> b) -> (c -> d) -> (Tuple a c) -> (Tuple b d)
51+
```
52+
We take two functions, `f` and `g`, and we transform them into a single function which
53+
takes a `Tuple` and maps `f` over the first element and `g` over the second. Just like `bi-map`
54+
would do for the `bi-functor` instance of `Tuple`.
55+
3356
#### `(&&&)`
3457

3558
``` purescript
@@ -44,4 +67,11 @@ one side of the `Tuple`.
4467
This combinator is useful when assembling values from smaller components,
4568
because it provides a way to support two different types of output.
4669

47-
70+
Specializing `(&&&)` to function application would look like this:
71+
```
72+
(&&&) :: forall a b c d. (a -> b) -> (a -> c) -> (a -> (Tuple b c))
73+
```
74+
We take two functions, `f` and `g`, with the same parameter type and we transform them into a
75+
single function which takes one parameter and returns a `Tuple` of the results of running
76+
`f` and `g` on the parameter, respectively. This allows us to run two parallel computations
77+
on the same input and return both results in a `Tuple`.

src/Data/Profunctor/Choice.purs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ import Data.Profunctor
1010
-- |
1111
-- | `left` and `right` lift values in a `Profunctor` to act on the `Left` and
1212
-- | `Right` components of a sum, respectively.
13+
-- |
14+
-- | Looking at `Choice` through the intuition of inputs and outputs
15+
-- | yields the following type signature:
16+
-- | ```
17+
-- | left :: forall input output a. p input output -> p (Either input a) (Either output a)
18+
-- | right :: forall input output a. p input output -> p (Either a input) (Either a output)
19+
-- | ```
20+
-- | If we specialize the profunctor `p` to the `function` arrow, we get the following type
21+
-- | signatures:
22+
-- | ```
23+
-- | left :: forall input output a. (input -> output) -> (Either input a) -> (Either output a)
24+
-- | right :: forall input output a. (input -> output) -> (Either a input) -> (Either a output)
25+
-- | ```
26+
-- | When the `profunctor` is `Function` application, `left` allows you to map a function over the
27+
-- | left side of an `Either`, and `right` maps it over the right side (same as `map` would do).
1328
class (Profunctor p) <= Choice p where
1429
left :: forall a b c. p a b -> p (Either a c) (Either b c)
1530
right :: forall a b c. p b c -> p (Either a b) (Either a c)
@@ -24,6 +39,14 @@ infixr 2 |||
2439

2540
-- | Compose a value acting on a sum from two values, each acting on one of
2641
-- | the components of the sum.
42+
-- |
43+
-- | Specializing `(+++)` to function application would look like this:
44+
-- | ```
45+
-- | (+++) :: forall a b c d. (a -> b) -> (c -> d) -> (Either a c) -> (Either b d)
46+
-- | ```
47+
-- | We take two functions, `f` and `g`, and we transform them into a single function which
48+
-- | takes an `Either`and maps `f` over the left side and `g` over the right side. Just like
49+
-- | `bi-map` would do for the `bi-functor` instance of `Either`.
2750
(+++) :: forall p a b c d. (Category p, Choice p) => p a b -> p c d -> p (Either a c) (Either b d)
2851
(+++) l r = left l >>> right r
2952

@@ -32,6 +55,17 @@ infixr 2 |||
3255
-- |
3356
-- | This combinator is useful when assembling values from smaller components,
3457
-- | because it provides a way to support two different types of input.
58+
-- |
59+
-- | Specializing `(|||)` to function application would look like this:
60+
-- | ```
61+
-- | (|||) :: forall a b c d. (a -> c) -> (b -> c) -> Either a b -> c
62+
-- | ```
63+
-- | We take two functions, `f` and `g`, which both return the same type `c` and we transform them into a
64+
-- | single function which takes an `Either` value with the parameter type of `f` on the left side and
65+
-- | the parameter type of `g` on the right side. The function then runs either `f` or `g`, depending on
66+
-- | whether the `Either` value is a `Left` or a `Right`.
67+
-- | This allows us to bundle two different computations which both have the same result type into one
68+
-- | function which will run the approriate computation based on the parameter supplied in the `Either` value.
3569
(|||) :: forall p a b c. (Category p, Choice p) => p a c -> p b c -> p (Either a b) c
3670
(|||) l r = (l +++ r) >>> join
3771
where

src/Data/Profunctor/Strong.purs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ import Data.Tuple (Tuple(..))
1010
-- |
1111
-- | `first` and `second` lift values in a `Profunctor` to act on the first and
1212
-- | second components of a `Tuple`, respectively.
13+
-- |
14+
-- | Another way to think about Strong is to piggyback on the intuition of
15+
-- | inputs and outputs. Rewriting the type signature in this light then yields:
16+
-- | ```
17+
-- | first :: forall input output a. p input output -> p (Tuple input a) (Tuple output a)
18+
-- | second :: forall input output a. p input output -> p (Tuple a input) (Tuple a output)
19+
-- | ```
20+
-- | If we specialize the profunctor p to the function arrow, we get the following type
21+
-- | signatures, which may look a bit more familiar:
22+
-- | ```
23+
-- | first :: forall input output a. (input -> output) -> (Tuple input a) -> (Tuple output a)
24+
-- | second :: forall input output a. (input -> output) -> (Tuple a input) -> (Tuple a output)
25+
-- | ```
26+
-- | So, when the `profunctor` is `Function` application, `first` essentially applies your function
27+
-- | to the first element of a `Tuple`, and `second` applies it to the second element (same as `map` would do).
1328
class (Profunctor p) <= Strong p where
1429
first :: forall a b c. p a b -> p (Tuple a c) (Tuple b c)
1530
second :: forall a b c. p b c -> p (Tuple a b) (Tuple a c)
@@ -23,6 +38,14 @@ infixr 3 &&&
2338

2439
-- | Compose a value acting on a `Tuple` from two values, each acting on one of
2540
-- | the components of the `Tuple`.
41+
-- |
42+
-- | Specializing `(***)` to function application would look like this:
43+
-- | ```
44+
-- | (***) :: forall a b c d. (a -> b) -> (c -> d) -> (Tuple a c) -> (Tuple b d)
45+
-- | ```
46+
-- | We take two functions, `f` and `g`, and we transform them into a single function which
47+
-- | takes a `Tuple` and maps `f` over the first element and `g` over the second. Just like `bi-map`
48+
-- | would do for the `bi-functor` instance of `Tuple`.
2649
(***) :: forall p a b c d. (Category p, Strong p) => p a b -> p c d -> p (Tuple a c) (Tuple b d)
2750
(***) l r = first l >>> second r
2851

@@ -31,6 +54,15 @@ infixr 3 &&&
3154
-- |
3255
-- | This combinator is useful when assembling values from smaller components,
3356
-- | because it provides a way to support two different types of output.
57+
-- |
58+
-- | Specializing `(&&&)` to function application would look like this:
59+
-- | ```
60+
-- | (&&&) :: forall a b c d. (a -> b) -> (a -> c) -> (a -> (Tuple b c))
61+
-- | ```
62+
-- | We take two functions, `f` and `g`, with the same parameter type and we transform them into a
63+
-- | single function which takes one parameter and returns a `Tuple` of the results of running
64+
-- | `f` and `g` on the parameter, respectively. This allows us to run two parallel computations
65+
-- | on the same input and return both results in a `Tuple`.
3466
(&&&) :: forall p a b c. (Category p, Strong p) => p a b -> p a c -> p a (Tuple b c)
3567
(&&&) l r = split >>> (l *** r)
3668
where

0 commit comments

Comments
 (0)