-
Notifications
You must be signed in to change notification settings - Fork 92
Expand on documentation #217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
9464e86
276a5e5
c48a6e6
e7de566
da12208
7f4e169
8157482
285f934
0b62cf3
6587f19
bf1a5b4
0fb3e86
0bfaad0
ec6710f
2224347
5ab4e52
07bef30
8d79a6b
24f4ca7
d939da5
b424064
a608415
105a53e
85039e8
6e14a53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,20 @@ import Type.Data.RowList (RLProxy(..)) | |
| -- | `Monoid`s are commonly used as the result of fold operations, where | ||
| -- | `<>` is used to combine individual results, and `mempty` gives the result | ||
| -- | of folding an empty collection of elements. | ||
| -- | | ||
| -- | ### Newtypes for Monoid | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should save the specifics of each Monoid-related newtype to the definitions of the newtypes themselves. I suspect it be easier for people to understand these if they can see the rendered definitions alongside the documentation which says how they work, and also this would be very easy to get out of sync since the newtypes themselves live in separate files. I do think this is a good place to mention the issue that some types permit multiple Monoid instances, and that we can express this with newtypes, but I think it would be best to keep that discussion minimal here. Something like "For example, the Additive newtype has a Monoid instance which is based on Semiring's Also, I realise this is a bit of a nitpick, but I would also prefer not to call it a "workaround", because I think doing this means admitting that not being able to equip a type with two Monoid instances is a deficiency (I don't think it is).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agreed. Does my rendering work? Or are there other changes you would prefer?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks great 👍 |
||
| -- | | ||
| -- | Some types (e.g. `Int`, `Boolean`) can implement multiple law-abiding | ||
| -- | instances for `Monoid`. For example, `<>` could be `+` and `mempty` could | ||
| -- | be `0`. Likewise, `<>` could be `*` and `mempty` could be `1`. | ||
|
||
| -- | To workaround these ambiguous situations, one should use newtypes | ||
| -- | to specify which instance should be used: | ||
| -- | - `Additive`: use `Semiring`'s `plus`/`+` and `zero` for `<>` and `mempty`. | ||
| -- | - `Multiplicative`: use `Semiring`'s `mul`/`*` and `one` for `<>` and `mempty`. | ||
| -- | - `Conj`: use `HeytingAlgebra`'s `conj`/`&&` and `tt` for `<>` and `mempty`. | ||
| -- | - `Disj`: use `HeytingAlgebra`'s `disj`/`||` and `ff` for `<>` and `mempty`. | ||
| -- | - `Endo`: use `Category`'s `compose`/`<<<` and `identity` for `<>` and `mempty`. | ||
| -- | - `Dual`: use `Category`'s `composeFlipped`/`>>>` and `identity` for `<>` and `mempty`. | ||
| class Semigroup m <= Monoid m where | ||
| mempty :: m | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,16 @@ import Type.Data.RowList (RLProxy(..)) | |
| -- | - Associativity: `(x <> y) <> z = x <> (y <> z)` | ||
| -- | | ||
| -- | One example of a `Semigroup` is `String`, with `(<>)` defined as string | ||
| -- | concatenation. | ||
| -- | concatenation. Another example is `List a`, with `(<>)` defined as | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is definitely a good example to include here 👍 |
||
| -- | list concatenation. | ||
| -- | | ||
| -- | ### Newtypes for Semigroup | ||
| -- | | ||
| -- | There are two other ways to implement an instance for this type class | ||
| -- | regardless of which type is used. These instances can be used by | ||
| -- | wrapping the values in one of the two newtypes below: | ||
| -- | 1. `First` - Use the first argument every time: `append first _ = first`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These instances are a bit weird and somewhat rarely used, so I'm not sure they deserve a mention here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say they deserve a mention because it mirrors what is said in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just think that of all the things we might want to say about semigroups to someone encountering the concept for the first time, I think the First and Last semigroups should be fairly low down on the list, even if their newtypes do happen to live in this repository. While having some level of understanding of the Semigroup type class is more or less required if you want to use PureScript, I would argue that the First and Last semigroups are very much not required. I think it’s more respectful of the user’s time and energy to avoid mentioning things if we don’t expect that they will find them useful at the moment they are reading the docs in question.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then again, they are simple examples, and giving plenty of simple examples is always an important part of teaching these concepts, so maybe they do deserve a mention here. |
||
| -- | 2. `Last` - Use the last argument every time: `append _ last = last`. | ||
| class Semigroup a where | ||
| append :: a -> a -> a | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,23 @@ module Data.Void (Void, absurd) where | |
|
|
||
| import Data.Show (class Show) | ||
|
|
||
| -- | An uninhabited data type. | ||
| -- | An uninhabited data type. In other words, one can never create | ||
| -- | a runtime value of type `Void` becaue no such value exists. | ||
| -- | | ||
| -- | `Void` is useful to eliminate the possibility of a value being created. | ||
| -- | For example, a value of type `Either Void Boolean` can never have | ||
| -- | a Left value created in PureScript. | ||
| -- | | ||
| -- | This should not be confused with the word, `void,` that commonly appears in | ||
|
||
| -- | C-deriving languages, such as Java: | ||
|
||
| -- | ``` | ||
| -- | public class Foo { | ||
| -- | void doSomething() { System.out.println("hello world!"); } | ||
| -- | } | ||
| -- | ``` | ||
| -- | | ||
| -- | In PureScript, one often uses `Unit` to achieve similar effects as | ||
| -- | the lowercased `void` above. | ||
|
||
| newtype Void = Void Void | ||
|
|
||
| instance showVoid :: Show Void where | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that
Monadis the best place to put documentation for do-notation. There isn't anything requiring aMonadinstance in order to use it. This is a common Haskellism, since Haskell requires it, but if you already know to look for that, is this communicating new information?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it might be helpful for new users who are learning FP for the first time.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand, and I don't think your intentions are misguided. I'm also not trying to say that the information isn't useful. My point is that core library documentation should strive for correctness. It is not correct to say that do-notation has anything to do with
Monad(unlike Applicative-do, which certainly requiresApplicative), even if we colloquially tie the two together. It's a common case that when you use do-notation, you likely also have a Monad instance, but this is not a constraint of the language or compiler. If I were a newcomer looking for information on do-notation, it is not clear to me that theMonadtypeclass documentation is the best place to put this information. It also is not clear to me that a newcomer is likely to encounter do-syntax for the first time by reading the documentation forMonad.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah... because you can also do what I recall that you do with
do(wow... that was a convoluted sentence 😆 ):where "do notation" is a somewhat cleaner way of writing "let-in" blocks.
Good points! I thought having it here would be nice because one could find something like it in Pursuit when they search for things. However, I agree that there are other forms of documentation (e.g. the book, my repo) that cover it already and might be something new users consult first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should also note that what I said was incorrect as well. Applicative-do does not "certainly" require
Applicative, since it just inserts calls toapplyandpurein scope, even if the common use is with theApplicativeclass.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with removing both of these do/ado notation docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the do/ado notation explanations in latest commits.