Talk:Monad (functional programming)

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search

We should dehaskelize it[edit]

There's a big problem with this article. It's all Haskell. That's not good. We have to be more abstract. Maybe write a bunch of paragraphs regarding how a monad looks like in Scala, Java, JavaScript, C++, Rust, C#, etc. Vlad Patryshev (talk) 19:27, 4 January 2017 (UTC)

Haskell is a huge contributor to the use of monads in functional programming, so it's logical that many sections are based on documentation written in it. (Some may say that writing in Haskell is being "more abstract"). We have examples in Javascript and F#. If you know of references that document the usage of monads in those other languages, by all means bring them here and we'll figure out the best way to include them in the article. Diego (talk) 09:55, 5 January 2017 (UTC)
A Haskell-oriented explanation would be OK if it also explained enough Haskell details used so readers needn't already know Haskell to follow along. Grokking monads is difficult so we can't really expect readers to simultaneously make lots of successful inferences about Haskell. This is doubly important since you can't get far in Haskell in turn without understanding monads.
Please explain the syntax used, also its precedence (or use enough parentheses to avoid that). Are newlines significant? What determines which monadic type's Just, return, or >>= get called in presented example expressions such as Just 10 // Just 5? Type classes, parameterized types, operator overloading, type inference, (), ... What's the relationship between Just, unit, and return? When the article says “a monadic value: M a”, is that really a variable, a type, or both?
An alternate way to explain monads would be in a more familiar programming language. Using an object oriented language would answer the question of which Just and bind get called, but it ought to be a language where types are first class values like JavaScript, Ruby, or Smalltalk.
That said, this page has improved dramatically over the last few years. 73.93.185.77 (talk) 01:55, 12 January 2017 (UTC)
I'm afraid explaining the syntax of Haskell is outside the scope of this article. What it could do is better identify what features of the language are used in each example (enumerated types, pattern matching, etc).
Adding examples in imperative languages wouldn't be a good idea, methinks; monads and object-orientation don't mix well, as the contrived Javascript example shows. IMHO one should have at least a basic grasp of functional programming before trying to understand monads; this is the scope where they are more useful anyway.
In imperative languages you can use mutable state, so one of the main selling points of monads for strict functional languages is not needed there. And the other uses, for handling data structures and control threads, would require a syntax in an imperative language too awkward to be useful. Diego (talk) 13:29, 12 January 2017 (UTC)

External links modified[edit]

Hello fellow Wikipedians,

I have just modified one external link on Monad (functional programming). Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:

When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.

As of February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete the "External links modified" sections if they want, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{sourcecheck}} (last update: 15 July 2018).

  • If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
  • If you found an error with any archives or the URLs themselves, you can fix them with this tool.


Cheers.—InternetArchiveBot (Report bug) 19:46, 5 April 2017 (UTC)

More Haskell and the image in the lead[edit]

Sixth root as a composite function of cbrt and sqrt.svg

The structure that defines the input type and how to compose the different actions together is a monad.

The complex multivalued square and cube root functions may be composed with the "bind" operator "•" so they produce the sixth root function. Here z is a complex number, and the square brackets denote an array.
  • unit(z) := [ z ]
  • (fg)(z) := append(map(f,g(z)))
  • lift(f) =  := unitf = funit
  • sqrt°(z) =
  • = append(map(unit,sqrt(z)))
  • = append(map(sqrt,unit(z)))
  • sxrt(z) = (cbrt°sqrt°)(z) = append(map(cbrt°,sqrt°(z)))

@Diego Moya: you wrote about the lead image It doesn't say how the structure correlates to the monad's return and bind operators. That's true; monads aren't just a concept in Haskell and that diagram represents a monad that's not in Haskell... Now I'm not going to suggest splitting the article into Monad (Haskell), but the lead has to acknowledge that Haskell's operators aren't the definition of a monad, and if the diagram describes a monad without relating it to Haskell it shouldn't be ruled out... Bright☀ 15:05, 9 May 2017 (UTC)

The bind and return operators are the name of the monad-defining operators in Haskell, but they are not exclusive from Haskell. The section Formal definition defines a monad with a type constructor, unit function and binding operation. The structure in the image should be explained in terms of these mathematical constructs for relating it to monads in functional programming. I reiterate here my concerns that, without a proper explanation, the image looks like an arbitrary selection of mathematical formulas, and it remains unclear how these relate to the topic of the article. How do we know the image represent a monad and not, say, a set, a lattice, or a directed graph? Diego (talk) 15:47, 9 May 2017 (UTC)
How do we know the image represent a monad and not, say, a set, a lattice, or a directed graph? 'cause the description says "The structure that defines the inputs, outputs, and how to compose the different actions together, is a monad." Bright☀ 20:09, 9 May 2017 (UTC)
Well yes, but then we need to trust the editor saying so, and we can't verify it by ourselves. It doesn't improve our understanding of what a monad is. Diego (talk) 05:40, 10 May 2017 (UTC)
BarAndRing.svg
It improves the reader's understanding since it gives a concrete (visual) example of what monads "do". It's not a standalone replacement for the entire article... Let me give you different examples. What the hell is the diagram on the left for? It's just a couple of ellipses and horizontal lines and three arrows. But if you throw in a description, "The bar and ring paradox is an example of the relativity of simultaneity. Both ends of the bar pass through the ring simultaneously in the rest frame of the ring (left), but the ends of the bar pass one after the other in the rest frame of the bar (right)", it becomes an example of the relativity of simultaneity. You can't verify it without the description because it's just a bunch of symbols, but that doesn't mean it doesn't improve the reader's understanding. For all of this, a reader who's never seen an apple can't verify that a photo of an apple is a photo of an apple if it doesn't have a description saying that it's a photo of an apple, accompanied by an article that describes what is an apple.
Anyway I'm not going to pursue it further. Bright☀ 06:17, 10 May 2017 (UTC)
The key in that second example is that it contains the sentence "ends of the bar pass through the ring simultaneously in the rest frame of the ring (left), but the ends of the bar pass one after the other in the rest frame of the bar (right)". I.e. it explains the parts of the image in terms ot the topic. I agree it would be useful having a visual example of the monad, but it needs to be explained with a similar sentence detailing the elements in the image. (The current explanation mentions inputs and outputs, but those are not part of the monad). Diego (talk) 06:24, 10 May 2017 (UTC)
@Diego Moya: I've tried making the structure of the monad explicit, please inspect. Bright☀ 16:51, 11 May 2017 (UTC)

───────────────────────── Thanks, that's the kind of detail I was talking about. Something similar to that image could be a good addition to the lede.

I still don't understand how the structure is a monad from that image, though. The binding operation is a binary function that returns one value, though the arrows for bind in the image make it have one input and two outputs. Is this an instance of currying? In the same way, the unit function return takes on parameter, yet the box in the image takes two inputs. Could you make the labelled boxes map to the parameters in the formal definition of the monad? Diego (talk) 07:55, 12 May 2017 (UTC)

Sorry, I put bind and return instead of map and append... I'll fix it. Bright☀ 16:04, 12 May 2017 (UTC)
Made the description explicit, but now it's very long. Bright☀ 21:32, 12 May 2017 (UTC)

Expert on functional programming needed[edit]

An expert with a great, deep, no-nonsense understanding of functional programming in general (not just a particular language-specific expert) is needed to clean up this article from all the Haskell-specific tone, examples and references and make it what its title says it should be, i.e. a true article about monads in functional programming in general.

Reasoning[edit]

As many people have noted in this discussion, this article does a poor job explaining what a monad is in the general context of functional programming. It shows what a monad in Haskell is and as such it can be renamed to "Monads in Haskell". But a true article on monads in functional programming in general is needed.

An expert should split out this article into two articles. First should be about monads in Haskell and it may retain most of the original article's content. It will then be up to Haskell experts to clean it up. The second, generic article should be about monads in functional programming in general. It should retain the current title and assume the place of the current page. It should provide a succinct and easy to understand explanation of what a monad is in the general context of funcional programming. It should also explain the motivation behind introducing and using monads in general, before referring to the use cases in any specific programming language.

pbasista (talk) 12:47, 25 July 2017 (UTC)

@Pbasista:, take into account that articles are written in relation to the available sources, and the majority of sources regarding monads are based on the Haskell language. Do you know a good reference that treats monads in the context of functional programming in general, that we could follow to expand the article in that direction? Diego (talk) 15:29, 25 July 2017 (UTC)
@Diego Moya: Duly noted. I am not aware of any good resources on monads in functional programming in general and that is why I have suggested that an expert should look into it. There is a related stackoverflow question, which has some answers, e.g. this one, that explain the topic in a programming-language-independent way. Or there is this article, which is Python-specific, but has a section called "Generalisation - Monads" further down, where it uses a generic terminology. So, there are generic resources that are not specific to any functional programming language, but they need to be carefully picked and summarized in this article by an expert. pbasista (talk) 17:21, 25 July 2017 (UTC)

I'm actually looking for a place to stick my non-Haskell example, but the article is so focused on Haskell there's no section where the image and its description could fit. Bright☀ 16:02, 28 July 2017 (UTC)

Archived discussion prior to 2017[edit]

I've archived all discussion prior to 2017. It's important to note that many editors pointed out that this article is too Haskell-centric and poorly structured. Bright☀ 17:08, 30 July 2017 (UTC)

External links modified (January 2018)[edit]

Hello fellow Wikipedians,

I have just modified 3 external links on Monad (functional programming). Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:

When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.

As of February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete the "External links modified" sections if they want, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{sourcecheck}} (last update: 15 July 2018).

  • If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
  • If you found an error with any archives or the URLs themselves, you can fix them with this tool.


Cheers.—InternetArchiveBot (Report bug) 11:36, 21 January 2018 (UTC)

External links modified (February 2018)[edit]

Hello fellow Wikipedians,

I have just modified one external link on Monad (functional programming). Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:

When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.

As of February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete the "External links modified" sections if they want, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{sourcecheck}} (last update: 15 July 2018).

  • If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
  • If you found an error with any archives or the URLs themselves, you can fix them with this tool.


Cheers.—InternetArchiveBot (Report bug) 07:16, 4 February 2018 (UTC)

Formal definition before Haskell[edit]

As part of the efforts to make this article less Haskell-oriented, I suggest placing the formal definition section first. Additionally, I will use the terms from the formal definition in the sixth root example to make it clear which part is which, particularly the arrows that are easy to miss. Bright☀ 15:00, 24 April 2018 (UTC)

The image became too crowded with descriptive text next to each element, so I added it in the description instead. It fits well next to the formal definition. Bright☀ 17:11, 24 April 2018 (UTC)

Formal definition should be clarified[edit]

The "Formal definition" section presently says that:

Typically, the binding operation can be understood as having four stages:
  1. The monad-related structure on the first argument is "pierced" to expose any number of values in the underlying type t.
  2. The given function is applied to all of those values to obtain values of type (M u).
  3. The monad-related structure on those values is also pierced, exposing values of type u.
  4. Finally, the monad-related structure is reassembled over all of the results, giving a single value of type (M u).

This doesn't seem to follow from the provided signatures. I suggest this explanation instead:

  1. The monad-related structure on the first argument is "pierced" to expose the value of the underlying type t.
  2. The given function is applied to the value to obtain a value of type (M u).

And that's all. Whether the underlying type t is a collection type or not is irrelevant and should be handled by the provided function. If this is not the case, and the structure must indeed be pierced twice, then some explanatory text should be added to explain the importance or utility of this practice. 2001:4200:1010:1078:325A:3AFF:FE7E:3341 (talk) 14:00, 1 August 2018 (UTC)

Page Rewrite (October 2018)[edit]

Hi there, I've had this article on my radar for a while, and I hope my changes are for the better. I don't claim to be an expert, but I've studied some category-theory, logic, and language-design so I think I can help help push the article forward some. If anyone decides to revert or has a comment, I'll be keeping an eye on this talk page. So if you leave some feedback here, I'll take it into account going forward.

I plan to move down the article from top to bottom, though I'll give everything a second pass to proofread, maybe change the section organization some too. I also don't plan to mess with the code examples much, if I do at all. For now, my main goals are just to whittle the article down, explain things as clearly as I can without referring to symbols, and spruce up the links and references.

I'd say I've made two major changes so far:

  • I cut the "safe division" example because I felt the "Maybe add" function already hit the same points plus some. If everyone wants to bring it back though, I can do that in a different part of the article that flows bet:ter.
  • I've also been using the words "unit" and "bind" in bold to discuss the monad operators. I know the goal was to de-Haskellize the article, but I personally wouldn't mind defining Haskell-ish symbols in the overview and using them throughout. However, I do think we should emphasize the name "unit" instead of "return" outside of Haskell examples. "Unit" matches the original category theory, Wadler's early paper, and is more intuitive in my mind, whereas AFAICT "return" is popular only because Haskell uses it to make do-notation look more imperative.

One last point is I've added some references that point to Haskell's wiki and documentation; I figured that isn't a problem as long as we aren't bringing over the language-specific terms or syntax. I could see a non-wiki source being more ideal too, but I figure the official Haskell wiki is relatively authoritative. Zar2gar1 (talk) 21:34, 8 October 2018 (UTC)

How does a monad differ from a class? -Inowen (nlfte) 06:44, 11 November 2018 (UTC)
Please see type class. (Haskellers use 'class', which is not the same as the object-oriented class. For them, class is an abbreviation for type class.)
Mac Lane, Categories for the Working Mathematician: "A monad is a monoid in the category of endofunctors." We can't have that slogan in the article, as it amounts to a distraction, while the article is in process. Can we take this to your talk page, please. --Ancheta Wis   (talk | contribs) 11:45, 11 November 2018 (UTC)
My question was about the novice idea of monads being akin to classes in oop, which is naive but I think its common and thus something to address. -Inowen (nlfte) 12:53, 11 November 2018 (UTC)
But the novice, by so phrasing, has shown it would have been better to have remained silent until the question has reformulated itself in the mind of the novice. Please see your talk page. --Ancheta Wis   (talk | contribs) 16:00, 11 November 2018 (UTC)

@Zar2gar1, The OOP terminology is harming the article. Do you plan to scrub it out? I added a useful citation. The Haskell Wikibook on the State monad is another resource. It may be useful to explicitly state that lists are monads in the lede, to give the reader a concrete example of the parallel between list comprehensions and the wikibook example: rollDie = do generator <- get feed to patterns from a monad. --Ancheta Wis   (talk | contribs) 17:37, 11 November 2018 (UTC)

@Ancheta Wis: Hi there, I didn't really have specific plans for hints/references to OOP ideas either way. On my first pass, I considered notes on how certain functional ideas might correspond to OOP just because I figure a lot of people come to functional programming from more of an OOP background. I decided they were just distracting though and took them out.
There are two places I personally see some value in keeping OOP-ish ideas. The first is I kept the "design pattern" part of the lede definition; I couldn't really think of a better way to get across that monads are abstract and not unique to Haskell, or even functional languages, without getting bogged down in category theory. The second is that, IIUC, the generic classes like Monad and Functor pretty much do work like interfaces in Java. I think it might be counter-productive not to have some links to OOP concepts there, like inheritance and encapsulation.
Like I mentioned above, my background is more in category theory and logic, and I've studied Haskell and some other functional languages from more of a design perspective. I expect that will color my edits in ways that others can improve on. Also, I only occasionally edit Wikipedia as sort of a hobby when I don't have much else going on (and as warm-up for doing research IRL) so you and all the other editors have my blessing to hack away at anything I've written. You don't have to worry about me taking changes personally or starting any edit wars.
My only request is if everyone could hold off just a few days more on:
  1. Changes to specific notation in the examples
  2. The bottom part of the article
I'm actually just about to make my last edit on the "Variations" section, and then I should be done with my second pass sometime later this week. After that, I'll take down the Restructure template and explain my notation choices here on the talk page. I would definitely appreciate others working over my changes at that point though. If I have the time and inclination, I might work up a navbox or two to add, but otherwise, I'll be finished. Zar2gar1 (talk) 18:55, 11 November 2018 (UTC)
@Zar2gar1 Here is a synopsis from a tutorial ala Hudak (2000) p.253 (I include it here because Hudak is out of print. Hudak notes that a Haskell keyword 'do' signals that a monad is at work. Hudak actually chains e1; e2; e3; e4 etc):
{- e1; e2; e3; ... are monadic expressions; p is a pattern returned by e1, which then feeds into e2. e2 yields a new pattern to feed into e3, etc.  -}

do e1 ; e2      =        e1 >> e2
do p <- e1; e2  =        e1 >>= \p -> e2
The above is the gist of Hudak. To me, the sequence e1; e2; e3; e4; ... explains why monads are 'programmable semicolons'. If the pattern p fails, the monad might simply select a new behavior from the next expression feeding from p into e2; e3; etc.. That is why I am so cautious about 'typeclass'. Each typeclass is for a different behavior. 'fail' or 'error' might well be inappropriate behavior, depending on the application. A 'lift' might be what is needed, when an appropriate pattern surfaces. --Ancheta Wis   (talk | contribs) 07:21, 12 November 2018 (UTC)
@Ancheta Wis: So first off, since both you and Diego explicitly mentioned moving some mention of List back into the lede, I'm going to do that (along with Maybe). I'm going to hold off on any specific examples or further explanations in the lede though, for the reasons I gave in my reply to Diego. But if you and the other editors come to an agreement on adding it in, I don't see a problem.
As for the Hudak reference, it's a good find and can probably work in several spots, but I don't know if it precludes us from mentioning type classes in the article. Reading the parts you quoted in context, I get the impression he's not saying that each monadic expression can have wildly different behavior (though I guess they could if you're using the Continuation monad). Instead, I think he's trying to explain the syntax and laws of monads without actually defining one. To have a working monad, you would have to define the specifics of the required operators, which imposes a unique behavor (corresponding as you said to a unique type class).
It's been a while since I studied Haskell in detail, but I vaguely remember "pattern matching" meaning something more central to the compiler in Haskell too, almost like a syntax-based variation on type checking. I could be wrong (plus I think more recent versions of Haskell don't have the same fail function), but I think the idea is that fail was a default exception that the compiler would throw if it caught a type mismatch in a monadic chain. Like you said, that might not be ideal so you could always define your own custom fail, but at that point, you would essentially be deriving/building a new monad (with a new type class). Zar2gar1 (talk) 22:47, 12 November 2018 (UTC)

@Ancheta Wis who dislikes treating common novice ideas; for you I coin the word "expertine." The novice idea of a monad is something like a class, and then writing about the difference is useful. -Inowen (nlfte) 19:36, 11 November 2018 (UTC)

Lede section[edit]

@Zar2gar1: I've worked extensively on the previous lede section, and I'd want to negotiate putting the essence of my contributions back in the article. I believe it is essential that, for a highly abstract topic like this, the introduction contains as much concrete concepts as possible. My concern is that sentences like "a monad generically transforms underlying data types into richer types with some standard higher-order functions (also called "functionals") that must obey formal rules", don't really explain anything to anyone who doesn't already know and understand all those difficult concepts, which require a big deal of knowledge about functional programming and/or formal systems.

I kept adding to and rewriting the section with the target audience of a developer with ample experience in imperative programming in industry, and who is trying to learn about pure functional programming for the first time (probably by researching what Haskell is about, and being told that Monads is the way that side-effects and state are handled). That's the profile of people I've met which is more confounded by monads, and who would benefit from a generic introduction not placed in the context of a FP course. That audience would benefit of noting concrete examples such as the Maybe and List monads, mentioning the bind and unit operators used to define the monads, and explaining as early as possible terms like "monadic variable/value"; as well as showing actual working code using monads, which the "safe division" provided at the start of the Overview section.

I feel that the new lede section does not say anything about the structure of the monad, barely anything about how they are used in a program, or practical reasons why you'd want to use them. For the sentences that appear explained in both versions (chaining functions in a pipeline, supporting referential transparency...) , probably we should use the more concise wording in your version. But I really think that we should also include all the other concepts that were present in the older version, and which helped put the concept in the context of programming at large, not exclusively with respect to functional programming as it is now. Diego (talk) 16:27, 12 November 2018 (UTC)

@Diego: I'm glad to hear from you because I've noticed you have seniority on this article. I would be fine meeting somewhere in the middle on the section, and with your feedback, I see a few changes I can make that we would probably agree on. Beyond that though, I'll just try to explain my approach, starting with the general points:
  1. Perhaps my main goal was just to whittle the size down some, per MOS:LEADLENGTH. If you look at my changes to the Overview closely, you may have noticed that I actually just moved a lot of the details from the lead further down (like the list of applications).
    1. That said, I don't see any problem with fattening up the 3rd paragraph, or even bumping the lead back up to 4 paragraphs and moving some central points back in.
    2. In particular, a short sentence that previews Maybe and List, and another acknowledging category theory would both be good additions. I just prioritized cutting the length over keeping those things in the lead.
  2. Another way our versions differ is that I tried to avoid any assumptions of imperative or OOP background in the lead. Now, in retrospect, I probably went too far the other way and over-linked to FP concepts (I'll make another pass to try fixing that). I have more to say below, but I think the ideal for the lead is to avoid both and aim for the simplest English and programming concepts possible.
    1. You're probably right that the vast majority of readers that come to the article do have programming experience. Even then though, I think moving details geared towards that audience into the Overview or other relevant sections is a small price to pay for keeping the lead as accessible as possible.
    2. Like I mentioned above, I'm personally for short hints and links to concepts from other paradigms as long as they pop up naturally. I'm just not sure that's really possible in the lead.
    3. The "programmable semicolon" idea is nice because it can fit in a single clean sentence, but it seems that without a disclaimer right next to it, a lot of readers fall into the trap of thinking monads order operations.
    4. I also removed the reference to the "assembly line" metaphor because (although I think it's one of the better metaphors because it brings the intuition of "automating" things) it still has a strong "monads order operations" flavor. Also, while I'm normally very fond of metaphors, I'm hesitant to keep any in the article because of the "monad tutorial fallacy" and people's tendency to form subjective opinions about which metaphors are better (like I just did a sentence ago). I really think the only way to win the monad metaphor game is not to play.
  3. On the safe-division example, I think it's a good code-snippet and kept the F# version in the do-notation section, but I felt the Haskell version at the top sort of distracted from the more fleshed-out example that used add.
    1. Otherwise, I thought the Maybe example belonged at the close of the Overview. I do think mentioning the three monad components first helps motivate the example, but otherwise, it was mostly a stylistic choice. If the consensus is to move it to the top of the Overview, I don't see a problem with that, especially if we can somehow distill the conceptual definition into the lead.
So those are the issues I have a clear opinion on, but how to address the technical FP concepts in the lead? I'm honestly more ambivalent about that, and I know my edits can be improved upon in that regard. Since the guidance is to avoid uncommon terms when possible, then provide context and wikilink when they're unavoidable, my approach was to take the bull by the horns, link to the FP concepts I felt were central to the article (like referential transparency), then try to smooth them away into simpler terms. After thinking about it, even though it's really hard for an idea like monads, I think the goal should be to strive for even more plain English in the lead, not to bring the technical stuff to the top or piggy-back off of other programming concepts.
I'm glad you brought up my one sentence too because I'll agree it's definitely stilted and not plain-spoken enough, but in retrospect, what I was trying to do with that sentence hints at what might be a way forward. For monads, it just might not be possible to affirmatively explain the concept without details and exposition that really don't belong in the lead. What we could do though is try to delimit the concept as much as possible by hinting at related concepts and carefully choosing intuitive terms to nudge the reader away from the usual fallacies.
So in that one sentence you quoted, without ever mentioning them, I was trying to convey the inutition of parametric polymorphism ("generically") via a functor ("a monad... transforms types") with additional structure ("richer types with some standard higher-order functions..."). That last bit in particular is still too stodgy now that I re-read it, but I stand by the idea of trying to hint at the main points without ever mentioning them.
So those are my pretty much my thoughts on the matter. Besides quick summaries of the history, examples, and use-cases, I think the main goal for the lead should be, with as little technical language as possible, to plant a few main intuitions in the reader's head:
  • Monads are not specific to a language or a framework
  • They rely on parametric polymorphism, not ad-hoc polymorphism, subtyping, overloading, etc. bounded polymorphism, not overloading concrete types
  • They allow modeling computations, not just pure functions
  • They actually reify the computations and are referentially transparent
  • A monad encapsulates bookkeeping code around ordered computations; it doesn't order the computations itself
  • They are not passive things attached to types, but functors with added structure that act on types
I want to finish my 2nd pass over the bottom of the article first, but then I'll definitely work over the lead again, incorporating this discussion. After that, I can accept whatever everyone else decides going forward. Zar2gar1 (talk) 21:54, 12 November 2018 (UTC)

Haskell[edit]

Zar2gar1 you are doing a giant disservice to the article by focusing it around Haskell instead of the general concept of a monad. There has been years of discussion about making this article less Haskell-centric and here you go making it completely focused on Haskell. Bright☀ 12:51, 14 November 2018 (UTC)

I would go as far as undoing all your changes since you're just making this article a Haskell textbook. Bright☀ 12:54, 14 November 2018 (UTC)
Phrases like First, assume a... or If this seems like unnecessary hair-splitting or we will first pin down... and a general style of addressing the topic as a textbook or lecture supplement is against Wikipedia policy. Bright☀ 13:01, 14 November 2018 (UTC)
The issues and motivation for using specific languages such as F# and Haskell are discussed above. I think it is clear that the section above is a roadmap. The concepts under discussion are abstract, and a specific language is not the point. Once the concepts are clear and concrete enough to the readership, then we can lift up the text. The similarity to mathematical notation ought to persuade the readership, but we are on a waypoint on a path, to the stated goal of freeing the content from specific syntax. --Ancheta Wis   (talk | contribs) 16:38, 14 November 2018 (UTC)
@BrightR: I'm sorry you feel that way, but I'm not really clear on how I've made the article more Haskell-centric. I've tried to move specific mentions of Haskell (outside the do-notation and IO examples) to either the History section or explanatory notes. I've also been trying to convert all definitions and the main examples to pseudocode; since it's about an inherently functional concept, I think a functional pseudocode would be better than pure mathematics (and trying to shoehorn in too much imperative pseudocode would get messy real quick). There's really no guidance for that though so I've had to put it together as I go along. I plan to summarize all my style choices for the pseudocode here on the talk page once I finish later this week, then let everyone change it as they will.
As for the diagram, it's a really good flowchart for picturing how the List monad can work, but I think it does have some issues. First, I moved it towards the bottom of the section because that's where the List example is discussed specifically. Also, the very last paragraph of the List subsection now describes the specific example drawn in the diagram, which cuts down on the image's caption and places it in context within the article.
On a more technical level, I'm worried that in the form you've reverted to, the diagram's list doesn't qualify as a monad. The way I interpret it, it's saying that acts on the list to break it apart, is applied freely to each value, then is used to stitch the two result lists together (so the end result is correct). though doesn't act on the functor (the list in this case), but is actually part of the functor that acts on morphisms / plain functions ( here). So while the ultimate idea is right, having it act on the list directly and separating out the values might mislead some readers; it also leaves open the possibility of applying different functions to the two intermediate results, which IIUC the monad would disallow.
Including is also a problem because while it makes List a monoid, it's distinct from which flattens nested lists and is the other necessary transformation. If you go back to the problem & solution in the source blog-post, you'll notice that he's using the Haskell function concat, which is actually different from a normal append and concatenates "elements of a container of lists" (i.e. nested lists): concat's specification within the Haskell prelude.
For lists, it's probably not a big deal, but for other monads (especially ones without an operator) it's a necessary distinction. We already discuss earlier so I feel it's more informative to give a pseudocode implementation for in the text, then refer to that in the diagram. Now, if the >>= operator bothered you in my version, I see the value of keeping operators out of the diagram and can take it out. I was going to spruce up the image one more time too, aligning the elements and using actual text for the labels (didn't realize at first that Wikimedia prefers not converting text to paths).
One other thing I'll agree with 100% is that I added some sentences with a conversational tone and the academic "we" in my first draft, and after a re-read, they did seem out of place. At first, my thinking was that it's common in research papers and expositions of technical ideas so it might be more appropriate here than, say, a culture article. I actually tried to clean some of it out on my 2nd pass but I'll keep an eye out for it when I skim the article one last time. For the overall flow of the article though, while I agree the sections should be topical as possible, I think the difficulty of the subject matter justifies a little bit of "walking through" the ideas with the reader. Zar2gar1 (talk) 22:28, 14 November 2018 (UTC)
Since you are trying to improve the article more than anyone in the past few years, here are some more considerations, other than not focusing on Haskell and not turning the article into a tutorial or textbook:
  • Get rid of the notes section. Information like monads as described in this article are technically what category theorists would call "strong monads" and the rest of the notes do not belong in a footnote, they belong in the body of the text.
  • Don't cut out explanations. "This is a list monad" is not an explanation. In particular if you take away all mentions of ° then half of the explanation disappears.
  • Don't alter the terms used in the references. If the reference uses "map" and "append", don't use different terms.
  • Use references....
Doing something to the article is a good start, but turning it into a tutorial or textbook is wrong. Bright☀ Bright☀ 15:17, 15 November 2018 (UTC)
Regarding "append/concat", the reference doesn't use Haskell concat, it uses the colloquial term "concat" in place of the list append function; see concatenation versus append, particularly the hatnot on the concat article. Bright☀ 15:11, 15 November 2018 (UTC)

Haskell and the flowchart[edit]

@BrightR, I have made the "Notes" section much larger, but I personally think footnotes are a great way to still provide technical details or specifics that might overload the average reader. If everyone agrees to undo that, I can accept it. You're absolutely right about using references too, and I have actually been collecting references as I write. It's just always been a personal preference of mine to first get all the ideas down, then go back over to add the citations, but I'll be working on that today.

I honestly still don't understand some of your criticisms though, like how I've made the article more focused on Haskell. You are right about the need to eliminate the conversational tone, but I don't think walking the reader through some examples or having later sections build on concepts in earlier ones makes the article a tutorial, especially for such a technical subject.

As for the flowchart, I really do like it in the article, and I respect the work you've put into it. After looking a little closer, I think I better understand what you're conveying with it too, but I'd still recommend tweaking it once more. For example, the diagram defines "•" as the bind operator and lift as "unit•f", but if you look in the blog post, the author uses "*" for bind and defines lift with "unit . f", which is simple function composition.

Also, I'll just register my concern one more time that when he uses "concat", he's referring to the Haskell function and simply appending lists wouldn't give you a well-defined bind. One more bit of evidence for that is that in his first example (implementing the Writer monad), he specifically says the following:

bind must serve two purposes: it must (1) apply f' to the correct part of g' x and (2) concatenate [my emphasis] the string returned by g' with the string returned by f'.

The solution immediately after that, however, doesn't use "concat" but the ++ operator. You might say he does that since ++ is just for string concatenation (though the author makes it pretty clear he's writing with Haskell in mind, where ++ is a more general concatenation). Then the question is though, if the author is distinguishing between concatenation for strings and appending for lists, why didn't he just use the word "append" in the list example to begin with?

Going deeper though (and I guess this shows the difficulty with just following sources in technical articles), I'm still not sure the blog post itself is entirely correct. It's a really good exposition, but if you look at the comments, many people pointed out typos and small errors so I think it has to be used carefully. I'll simply ask this: if "sqrt" and "cbrt" have to be lifted before going into the monad, what would the plain, unlifted versions of those functions look like?

I really don't mean to step on any toes, and I like seeing the flowchart in the article (I'd personally like to see even more diagrams). I just want to make sure it doesn't have subtle errors, and if it turns out to be fine, I'll apologize for so much nitpicking. Zar2gar1 (talk) 16:04, 18 November 2018 (UTC)

Trinot ∘ operator[edit]

There is a trinot(mp) = mp >>= (eta ∘ not(p)) pseudocode statement with a '∘' operator which is suggestive of composition, but I'm not sure. Since eta was defined with a parenthesized argument, does eta consume a 'tri-state' value peerhaps, or a monadic value? I ask since if x were a Nothing then Just (x+y) would appear to be ill-formed. Another way to ask this might be 'how would an eta( Maybe T) work?'. If the definition were for a monadic eta( Maybe T), I can see how the result could be Nothing. But not(p) could be Unknown, for a three-valued logic. Trinot might not short-circuit-evaluate to Nothing, and a fail could be the result for some definitions, as given farther down in the article. If I worry needlessly, I would welcome the reassurance. --Ancheta Wis   (talk | contribs) 17:48, 20 November 2018 (UTC)

@Ancheta Wis, sure thing. I'm glad people are willing to check my edits.
You're right that ∘ is intended as a run-of-the-mill, composition dot. I think the function is ok because the bind operator itself should act like a firewall and process undefined values so the other functions never actually see them. It can be checked by substitution; without getting bogged down in explicit variable binding (though looking at it now, I need to tweak the parentheses to follow my own convention), it should work something like:
mp >>= (eta ∘ not) p       ⇔
    if mp is Just p then   # Apply function only if value is defined
        (eta ∘ not) p
    else                   # Short-circuit otherwise
        Nothing
As for whether normal composition is justified, the output for not and input for eta should match up, and the overall input and output should conform to the proper signature T → M U (including possibly T → M T):
not(p) : Boolean → Boolean
eta(x) : T → Maybe T
(eta ∘ not) p : Boolean → Boolean → Maybe Boolean
Now you're right that if you tried cramming a Maybe value into eta directly, it would be malformed (and a strictly-typed language should throw an error). The one sort of tricky thing is that you could theoretically use eta (and unit in general) to repeatedly wrap a monadic value if you used map to lift it to the proper level first. Otherwise though, my understanding is that unit's type signature specifically requires a non-monadic value as input (and I'm much fuzzier on this, but I think even with monad transformers, each monad's level of nesting is sort of kept in a separate bucket).
More generally, I have finally settled on conventions for the composition dot and how to write function application, and I'll explain those once I'm done editing the article body. Zar2gar1 (talk) 22:59, 20 November 2018 (UTC)

RfC: Being Clear on "Classes"[edit]

After a little more thought about the discussion between Inowen and Ancheta Wis, I realized how unavoidable yet tricky the term "class" could be in this article.

In my edits, unless the context implies otherwise, I haven't really been using it with Haskell type classes or OOP classes in mind. I've been using the term in the mathematical sense, as in an absolute collection of things that isn't necessarily a set: Class (set theory). I don't really have a solution in mind beyond setting a standard sense in the lede with a wikilink, then making it clearer whenever the term is used differently. We should probably come to an agreement here though on what the standard sense in the article should be. Zar2gar1 (talk) 19:47, 11 November 2018 (UTC)

In my novice understanding the monad is like a class in that it is like a functional reuseable object. The understanding I have is that the differences go all the way down to the type of language object oriented or functional, and that makes it difficult for experts to draw comparisons without teaching about the fundamental differences between language forms. In whatever comparison, the key is to explain why they are different. -Inowen (nlfte) 01:08, 12 November 2018 (UTC)
@Inowen: Hmm, I'm not sure I entirely understand. When you say "the monad is like a class in that it is like a functional reuseable object," are you taking that as a definition? I think that might be problematic for several reasons; for one, that would imply that every function (and maybe even every constant value) is its own class, which at best, would only fit the usual senses of the word very trivially.
As I understand it, at least for this article, there are really three uses of "class" that might come into play:
  1. Type class is the Haskell-specific term for the sort of language feature that is typically used to implement monads. The most language- and paradigm-neutral term I've found for the feature is Concept (generic programming), but IIUC, Java's "generics" and C++ "templates" are (roughly) the same thing.
  2. Class (set theory) is the more mathematical idea, but it's not too complicated. To put it very loosely, you might say a class in set-theory is just a collection of things that's defined "top-down" whereas a set is inherently more "bottom-up". Don't take this as officially, rigorously true, but you could say a class in mathematics is a lot like a (non-enumerated) type in programming.
  3. Class (computer programming), which is about the OOP notion, isn't really the same because it's inherently constructive, not generic. Concrete OOP classes include actual definitions linked to specific types, but even abstract OOP classes only achieve ad hoc polymorphism. That's why it's important that the article doesn't leave anyone with the impression that monads form a class in this sense, individually or collectively.
As you can see, all three of those senses have their own articles and are pretty standard in their respective fields. In FP, you can implement a monad using a type class, and mathematically you can talk about the class of all monads (and sub/super-class relationships, like "monads are a subclass of functors"). Funny enough, you can even say that a specific monad induces classes of endofunctors... unless I'm getting mixed up (plus it's completely unnecessary for this article). Anyways, one has to use terminology carefully, but I don't think there's any significant, deeper relationship between the two things. It's just important that we make it clear, explicitly or by context, what we mean when we use the term in the article. Zar2gar1 (talk) 22:21, 12 November 2018 (UTC)