[Haskell-cafe] Constructors on left and right hand sides of equation

Richard A. O'Keefe ok at cs.otago.ac.nz
Fri Sep 19 05:05:25 UTC 2014


On 18/09/2014, at 7:56 PM, PATRICK BROWNE wrote:
> Thanks for the feedback.
> If both occurrences of (NewGlass i) in Eq1 reference the same object in memory then I would consider them to be the same.
> If they reference different objects I would consider them to be equal but not the same.
> Is (Fill m i ) in Eq 2 a type constructor? Is it treated the same as the data constructor (NewGlass i)?

Let's repeat the original code.

data Glass            -- missing comment
   = NewGlass Int     -- missing comment
   | Fill Glass Int   -- missing comment
   deriving Show

drink :: Glass -> Int -> Glass

drink (NewGlass i) j = (NewGlass i)   -- Eq 1
drink (Fill m i) j
  | full (Fill m i) = Fill (NewGlass (size m))  ((size m) - j)  -- Eq 2
  | i >= j = Fill m  (i-j)
  | otherwise = drink m (j-1)

First, (Fill m i) isn't *any* kind of constructor.
Second, the first occurrence of (Fill m i) is a (data) pattern
containing the (data) constructor Fill, and the second occurrence
of (Fill m i) is an expression containing the (data) constructor
Fill.  We may not know what Glass, NewGlass, and Fill *mean*,
but we know what they *are* (as Haskell thingies).

There are no objects, and "are these the same object" is
not a question that can meaningfully be asked about values
in a Haskell program.  (It IS a question that CAN meaningfully
be asked about the related language Clean, because Clean has,
or is alleged to have, a semantics in terms of graph rewriting,
where "node in graph" is not entirely unlike "object".)

As has been previously noted, two occurrences of "the same"
term need not have the same type.  I have often been tripped
up by this:

emap :: (a -> b) -> Either String a -> Either String b

emap _ (Left msg) = Left msg
emap f (Right val) = Right (f val)

works but

emap _ e@(Left msg) = e
emap f (Right val) = Right (f val)

does not work because the two occurrences of Left msg
have different types.

When the two occurrences *do* have the same type, it is
up to the compiler to decide whether they will refer to
the same place in memory or whether a copy will be made.
There is no test you can perform in Haskell to distinguish.
(It's the same in Prolog and Erlang and SML and F#.)

If it comes to that, consider a much simpler question.

f :: Integer -> Integer
f 123456789123456789123456789 =
  123456789123456789123456789
f _ = error "just an example"

Are the two occurrences of that big integer "the same"?
Who knows?  How could you tell?

Now consider

g :: (Char,Int) -> (Char,Int)
g pair@(_,_) = pair

I would like to tell you that multiple occurrences of the
same *variable* refer to a single copy of the data value,
but I can't find anything in the Haskell report to
guarantee this.  Maybe I didn't look hard enough.



More information about the Haskell-Cafe mailing list