Talk:Monad (functional programming)/Archive 2

Archive 1Archive 2

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.

This message was posted before February 2018. After 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 these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}} (last update: 5 June 2024).

  • 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

 

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)
 
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

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

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

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)

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.

This message was posted before February 2018. After 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 these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}} (last update: 5 June 2024).

  • 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)

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.

This message was posted before February 2018. After 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 these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}} (last update: 5 June 2024).

  • 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

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

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)

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

@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

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

@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

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"

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)

Going forward (Nov/Dec 2018)

Finally! It took much longer than expected, but the rewrite's finished. I tried to take everybody's comments into account and hope it's a net improvement. I've honestly sort of drained my writing battery for now, but I plan to keep an eye on the Talk page for a bit and will happily drop by for small requests or partial reversions if nobody else has the time.

I feel a lot of my choices should speak for themselves and have commented on a few already. There are several last thoughts I made notes of while writing though, and since it's a bit long, I've broken the comments into subsections; hopefully that isn't too taboo. Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

Last examples

It looks like I skipped the last few monads (Reader, State, and Continuation), but I actually did do some work on those. Instead of editing the article though, my proposed changes are in a draft on my user page: User:Zar2gar1/Monad table draft

I thought it made sense to condense all three into one subsection, then add details into tables. I started hesitating though and thinking it looks like too much of a data dump, but the main reason for not just adding it is simply that the Continuation monad bested me. I get what continuations are, how they work in simple arrangements, and what the more advanced procedures are doing conceptually.

From when I first studied it in Lisp though, call/cc honestly always seemed like witchcraft to me, and apparently it still goes right over my head. Anyways, I do think in their current form, with just brief descriptions and type signatures, these examples are still teasers, but I'm really not sure my version is any better, especially with the gaps. So what does everybody think? Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

There is a theory behind continuations, fortunately. To my knowledge, oleg-at-okmij (Oleg Kiselyov) is the Principal Investigator in the related fields at this time. --Ancheta Wis   (talk | contribs) 15:49, 27 December 2018 (UTC)
Yes, I think we may actually cite him in the article at a couple points already. IIUC, he actually works more on delimited continuations and zippers, but his site is definitely a good resource, and not just for this page.
As for finishing the table / redoing the section, my main problem isn't so much a lack of sources as it's simply on the edge of what I understand. I know I could finish it if I put in the time to study continuations more in-depth (and I would like to someday), but I just can't guarantee that will happen anytime soon.
Just to check though, do you like the idea of the table? Or should we stick closer to the current arrangement? I also put a request for expert assistance above the draft on my page, but I don't know if it registers with the WikiProject from User space. If it would help, I could move the request here onto the talk page or try personally asking real quick on the WikiProject page. Zar2gar1 (talk) 19:01, 30 December 2018 (UTC)

Style and pseudocode

Overall, being an FP article, I decided to keep definitions equational and use arrows to represent functions, so it does look vaguely similar to Haskell (though Haskell arguably just does that to look like math). I tried really hard though to avoid (outside of the footnotes) any previous knowledge of...

  • Currying, which I replaced with listed parameters.
  • Lambda calculus, particularly for binding variables within the monadic chain. I tried to mimic mathematical function application and let context explain the rest instead.
  • Sophisticated category theory (like adjunction.

As for wrapping/unwrapping the monadic type, I settled on Hungarian notation of all things. I know it's usually treated like the Nickelback of programming style (no offense if you like Nickelback), but this is one case where it just works.

There is a specific line I couldn't come up with a good style for though: the associative law for comonadic extend. The right-arrows in the monadic version may abuse notation slightly, but I feel they get across how the variables are being bound without complicating things. Unlike bind though, extend intuitively "connects" the terms first, then "rewraps" the result. In the end, I settled on the kludge to put both the operator and the right term in parentheses to emphasize that rewrapping comes 2nd, but I'm really not happy with it. It's like the application in lambda-calculus I tried to avoid, only more confusing because its implicit and backwards. I had some other ideas (like a "split" operator), but they would be extremely non-standard so I'm stuck and open to a different approach for extend.

Otherwise, everything came down to (or trying to) establish patterns and conventions that emphasize important distinctions:

  • Features defined for all monads/functors/etc. in general are cursive in prose (using <math> tags {{mvar}} templates), all other specific names and functions are wrapped in <code>.
  • Lower-case letters are used to represent things, upper-case letters for types.
  • Variables are mostly represented with x,y,z (I wasn't as consistent on this one and let a few exceptions slip through)...
    • In particular, p stands for "proposition" in the trinot function of the Maybe example.
    • Values that are instantiated by assumption and passed down the chain to functions typicaly use a,b,c.
  • Since monadic functions of type T → M U are the most common in the article, f,g,h are used to refer to them exclusively.
  • In the few instances where they're discussed, non-monadic functions use greek letters φ,χ,κ to represent them (most of these cases only pop up in the last examples)...
    • φ is for functions with distinct input and output types. Honestly, φ is just what I'm used to seeing in algebraic proofs for morphisms, plus it's how you transcribe f in Greek.
    • χ is for a function that outputs the same type; it comes after φ and transcribes to "ch" in English (different sound, but if you're being charitable, you could say "ch" stands for "change").
    • κ is for the (a → r) continuations used in that monad.
  • The composition dot ∘ works as in mathematics. It feeds one function's output to the next's input, but it cannot be used to apply a higher-order function to its parameter.
  • Like in mathematical notation, when an isolated function is applied to variables/values, parentheses are used, but when a compound function is applied, the compound is wrapped in parentheses (like (f ∘ g) x).
    • To avoid confusion, only a space separates a higher-order function from its parameter.

That should pretty much sum up the pseudocode, but again, I really have no personal attachment to any of these choices. If anything, I hope they're just a good start for others to build on. Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

Sorry for reverting your pseudocode. It claimed to be Haskell, so I made it so, but I should instead have just removed references to Haskell, which is what I've done now. There were also a few errors such as referring to Just T as a type: in fact Just X, where X is of type T, is a value of type Maybe T, and "Just T" confuses the value and type levels. I've fixed these. Hairy Dude (talk) 16:50, 30 June 2019 (UTC)
@Hairy Dude: No worries, there were actually a decent amount of changes even within a few months after I finished my edits in 2018. Describing the opening example as Haskell must have been added later. I'm more of a nomadic wiki-editor that likes to overhaul articles so I don't really stick around for repeated changes, but I saw your ping.
Plus while I personally don't know about some of the section additions & changes since then, I like most of the specific corrections & changes. I do wish the editor that put lambda-expressions back in had discussed it a little since I specifically gave my reason here for leaving them implicit (or using math-ish "f(x = a)" statements when variable binding needs to be explicit). I get where they're coming from too though so if readers generally prefer the lambdas, I'll consider it an improvement.
Now, there were several things I had in mind but were beyond my skill or time-investment; a much more focused list than all the debriefing notes I plastered this talk-page with. If you do return to edit this article regularly, feel free to tag me in a new talk discussion or section. Zar2gar1 (talk) 19:27, 6 July 2020 (UTC)

Proving the monad laws

I felt a quick demonstration of how to check the monad laws actually adds a lot to the article. It's very important from a theoretical standpoint, but most sources outside research papers skip over it.

That said, I'm not sure the approach I took to actually typing it up is optimal. I felt alignment was really important to keeping the proof clear, but in the end, the only way I could find to do that reasonably within a pseudocode box was very hackish (using HTML comment tags to insert padding). Doing it with LaTeX in a math box might be a lot simpler to align, but I wasn't sure if a block of math formatting would be off-putting for this article.

Does anyone else have experience with a similar situation? Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

Diagrams and pictures

Although (or because?) the subject is pretty dry, adding a few more images and a little more color to the article might be a quick improvement. I know it's purely aesthetic, but I always like when a page has a little eye-candy (silly as it sounds, I sort of miss how the examples were colored when given in Haskell).

One thing that comes to mind is including a couple screenshots from the programs listed in the Applications section, but a couple more diagrams might not hurt either. Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

Ideas for navboxes?

Since editing the article took more time and energy than expected, I won't be building some templates I had in mind. I was surprised though that there doesn't appear to be a "Functional programming" navbox (or an OOP one for that matter).

Maybe even more important though, I feel like a big part of understanding monads comes down to seeing how they relate to other concepts like functors. A more structured navbox, or maybe even something like this (though obviously simpler and with different relations) might really add to this and other articles. If it's done right, maybe it could even be useful for some category-theory articles.

I was also wondering if a good infobox for this article is possible and what that might look like. In the end, I kept coming back to the "design pattern" notion from the first sentence; it might be controversial at first since it would mix FP articles with a lot of OOP ones, but it would also make sense for articles like MapReduce. Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

A radical proposal for bind

While working on parts of the definition, a heretical idea popped into my head. I'm not really for or against it, but since we're trying to move away from relying on any particular language, what if we just used monadic composition (>=> in the Haskell sources, Kleisli arrows in math) for the default definition, and discussed bind as a technicality?

It's explained in most of the main sources, it avoids the weird traps with associativity and variable binding, and it arguably makes the connection back to category theory clearer. The only complication I could see is feeding values along the chain, but maybe even an explicit, pseudocode "input" function could take care of that. So for example, the monadic add from the top example would change from...

mx >>= (my >>= Just(x + y))

... to something more like...

(input >=> Just (x + y)) (mx,my)

Just a thought. Zar2gar1 (talk) 22:30, 29 November 2018 (UTC)

Dehaskellized example

Hello all, I have added yet another example to the "More Examples" section. See the edit here. (There are a couple other later minor edits for things like word order and periods.)

I would like to nominate this example to be instantiated as the "Overview" example, because I made it because I think it is one of the simplest possible concrete and informative examples of a Monad. Specifically, it does not rely on the reader knowing a topic like an option type (unlike the current Overview example) which personally confused me when I was trying to learn Monads on my own.

I recognize that my own example is still highly imperfect, and I am sorry if this post comes off as arrogant, but I would really like to help improve this page, and I do think that my example would aid in that.

edit: Sorry, I don't know what I was thinking when I wrote this. Chalk it up to being too excited about contributing.

--Kraic (talk) 21:21, 6 December 2019 (UTC)

Archive 1Archive 2