1

Reading this answer, I'm getting puzzled by the very first code fragment:

data Pair a = P a a

instance Functor Pair where
  fmap f (P x y) = P (f x) (f y)

instance Monad Pair where
  return x = P x x

  P a b >>= f = P x y
    where P x _ = f a
          P _ y = f b

What I see is the author redefining a data constructor two times and applying it to undefined variables.

First off, how does the second of the two definitions of P (those two that are found in the where clause of the instance Monad definition) matter if, as I believe, the first one (whichever we put first) always matches?

Second, according to what syntax rules could the expression P x y get evaluated when there are no expressions for x and y in scope, but rather some kind of a redefinition of a data constructor that happens to mention these variables' names?

Interesting to note that, if I instead write like:

  P a b >>= f = P x y
    where P u _ = f a
          P _ v = f b

— substituting u & v for x & y — I will observe an error: Variable not in scope for each of x & y, even though by all sane intuition renaming a bound variable makes no difference.

Ignat Insarov
  • 4,660
  • 18
  • 37

1 Answers1

9

The equation

P x y = z

does not define P, only x and y. This is the case in general: only the data and newtype keywords can introduce new constructors. All other equations define only term variables. To disambiguate between the two, constructors always begin with upper case (for the special case of operators, : counts as "upper case punctuation") and variables always begin with lower case.

So, the meaning of

P a b >>= f = P x y
  where P x _ = f a
        P _ y = f b

reads like this:

  1. Define a new function named (>>=). It is defined when the first argument matches the pattern P a b (binding a and b to the actual values P is applied to in the first argument), and when the second argument matches the pattern f (that is, always, and binding f to the value of that second argument).
  2. Apply f to a. Make sure the result of this matches the pattern P x _ (binding x to the first value P is applied to and throwing away the second).
  3. Apply f to b. Make sure the result of this matches the pattern P _ y (binding y to the second value P is applied to and throwing away the first).
  4. Return the value P x y.
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380