-1

Reading the internal

https://wiki.haskell.org/IO_inside

class Monad m where
    unit :: a -> m a
    bind :: m a -> (a -> m b) -> m b

I observe the term unit seems no longer used, and pure is the term now. Why? because I think pure is not adequate for such a recursive structure.

(>>=) is called bind here, and how do we call (>>)?

Functor
  • 582
  • 1
  • 9
  • 7
    There are only two hard problems in computer science, cache coherency, naming, and off-by-one errors. But don't worry. After a while, you can get used to any stupid name somebody else picked. (Try not to think about the fact that they think the name you picked is stupid, okay?) – Daniel Wagner Feb 14 '22 at 04:17
  • 3
    `unit` was never (AFAIK) used in any definition of the `Monad` type class. The page you are reading is written as if `Monad` is being introduced for the first time to handle IO, and as such is being much more literal in translating the mathematical concept of a monad into Haskell. The actual `Monad` method is called `return` (probably an even worse name). `pure` was introduced as part of the `Applicative` type class, before it was settled that `Monad` can just "inherit" `pure` from `Applicative` instead of defining `return` itself. (For backwards compatibility, `return` is retained.) – chepner Feb 14 '22 at 13:25

1 Answers1

4

The name pure is based on the idea that the monad (or applicative) represents some kind of effectful, "impure" computation in general, and that if you'd like to use a pure value/calculation as a component in your larger impure computation, you can embed the pure value/calculation within the impure computation with pure.

For example, if you have some applicative expression:

f <*> a <*> b

where f, a, and b are all impure applicative computations, and you'd like to replace the impure computation a with a pure value, you write:

f <*> pure 2 <*> b

and it's clear that you're passing a "pure" value of 2, or a "pure 2" as the first argument to the applicative function f.

As per @chepner's comment, the name unit was never used in actual Haskell implementations of monads or applicatives. That name comes from the mathematical definition, where monads can be defined as a type of monoid, and the "unit" operation is the identity element for the monoid. Identity elements are sometimes called units, presumably because the multiplicative identity in, say, the real numbers is "1" AKA unity AKA a unit.

Also as per @chepner, for historical reasons, there are two Haskell names for this operation -- pure is the the name used in the Applicative typeclass while return is the name used in the Monad typeclass. For all correct implementations of monads, these two operations do the same thing. The name return was probably chosen with the idea that a monadic computation of type Monad m => m a is a little "program" that might deal with some effects and then eventually return an a. If all you want to do is return an x :: a without dealing with any effects, you just return x.

The operator >> doesn't really have an official name. People usually use "and then" or simply "then" (see this answer). This comes from the idea that, when a monad is interpretable as a sequence of operations (e.g., the IO monad), the effect of a >> b is to first do a and then do b. There's also an operator *> that does the same thing (again, mostly for historical reasons -- >> for Monad and *> for Applicative), and it's also usually called "then".

K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71
  • Thanks for your elaborating answer. I also think `return` is a bad name and one of the source of confusion for beginners, and I imagine they named it for `do` notation and being "friendly" for imperative coders which should be a bad idea. – Functor Feb 14 '22 at 20:54
  • I think `pure 2` is not necessarily pure. imagine a monad which is the regular IO one except it also does something impure idempotently, e.g. creates some file in a certain directory if none was present, and does nothing otherwise. I think it's a lawful monad. `return` is unit wrt `>=>` and yet when run by itself is would also do this impure thing. am I missing something? – Will Ness Feb 14 '22 at 21:53
  • Note that I didn't mean "pure" and "impure" in the Haskell "is it I/O?" sense -- maybe I needed more scare quotes. For my purposes, `2` is "pure" and `pure 2` is "impure" in the context of *any* monad. Even in a boring monad like `Maybe`, the expression `pure 2 = Just 2` is "impure" because it's fiddling with the monad's effects via `Just`. My point was that, read aloud, the expression `pure 2` seems like a natural way of describing the use of a pure value embedded as part of an impure computation, by adding whatever required impure effects are "natural" for the monad. – K. A. Buhr Feb 14 '22 at 23:16
  • Now with *that* I can ageee completely but the answer seems to be saying the opposite, with the "... use a pure computation as a component in ... larger impure computation"... a "pure calculation" could be much clearer since "computations" imply "monadic". – Will Ness Feb 15 '22 at 02:38
  • Okay, that seems fine to me. Edited. – K. A. Buhr Feb 15 '22 at 03:10
  • @WillNess, if purity is judged relative to some external notion, how can you distinguish "these are never pure" from "these always have an impure interpretation"? – dfeuer Feb 15 '22 at 05:49
  • @dfeuer no word has meaning in isolation. The context here is the F/A/M's use of Haskell's intrinsic "pure" terms/calculations as denotations of external effectful "impure" computations. I'm using "calculations" after Wadler who used it after David Turner's KRC. I'll add the links later when I'm not on my phone. – Will Ness Feb 15 '22 at 06:54
  • @WillNess, I misspoke. Rather than "interpretation", substitute "interpreter". Maybe `runMyThingy m` always opens a connection to a database, even if `m = pure a`, but that seems more on `runMyThingy` than `pure`. – dfeuer Feb 15 '22 at 07:05
  • @dfeuer I'm just insisting on consistent terminology, without reading anything into the English word's meaning. The use of "pure" to refer to Haskell values is well established. The term/value `print 1` is pure. We intend it to represent some IO computation. The term/value `Just 2` is pure; we intend it to represent some early-termination-capable computation. That is all. Anything `Functor` is /can be used like that, is my understanding. – Will Ness Feb 15 '22 at 07:42
  • @dfeuer initially this answer called `pure 2` "pure computation" so I was responding to that. I thought the author was referencing the notion of `return` as a no-op so tried to come up with a counterexample. Turned out, they weren't. You replied to that first comment of mine but I read your reply from a different mindset already, so it was a bit of a miscommunication there, sorry for that. – Will Ness Feb 15 '22 at 15:02
  • the promised links: [my old answer](https://stackoverflow.com/a/15211184/849891) arguing that `pure` injects _pure values_ into an applicative functor's context; an [answer by Conor](http://stackoverflow.com/a/5847800/849891) which I thought relevant for some reason; it also deals with the pronunciation of operators; Wadler's paper is "Why calculating is better than scheming" and KRC is [Kent Recursive Calculator](https://en.wikipedia.org/wiki/Kent_Recursive_Calculator). – Will Ness Feb 15 '22 at 16:38