[Haskell-cafe] Newbie Question on type constructors

Ben Rudiak-Gould Benjamin.Rudiak-Gould at cl.cam.ac.uk
Mon Nov 1 13:09:12 EST 2004


Paul Hudak wrote:

> Oh, I disagree with this point of view.  Circle is certainly a value, 
> i.e. a full-fledged function, as Brian Beckman correctly surmised.

Interesting. I don't claim that my viewpoint is the One True Path, but I 
don't think it's wrong, either. I know you're interested in the teaching 
of Haskell, and the fact remains that I *was* confused by data 
constructors when I learned Haskell, and it *did* help me to stop 
thinking of them as functions. Different people learn in different ways, 
and that's how I learned; even now I find this view more natural than 
the view of constructors as functions. The wording of the OP's article 
made me think that he might be suffering from the same conceptual 
problem, so I tried to suggest the approach which worked for me.

> The Haskell designers did not decide "for convenience" that Circle is 
> the same as \x -> Circle x.  Rather, that's a fundamental law (the eta 
> law, to be exact) of the lambda calculus, on which Haskell is based.

I think you're begging the question here -- the eta law applies to 
functions -- but maybe you're just elaborating on your view rather than 
arguing for it, as I was. (I.e. I was elaborating, not arguing, when I 
said that Circle was a function "for convenience".)

> The real reason that the Haskell designers chose to have constructors 
> begin with a capital letter is to make pattern-matching clearer.

Certainly it's odd to be able to match on the result of a function. 
"case factorial (2*3) of factorial n -> ..." won't work, so it's 
surprising that "case Circle (2*3) of Circle x -> ..." does, if Circle 
is a function. On the other hand, if "Circle 6" is just a literal value, 
it's not at all surprising that "case Circle 6 of Circle x -> ..." does 
what it does. And, at least for me, that extends to "case Circle (2*3) 
of Circle x -> ..." as well. (*) is being called in this example, and is 
returning an entirely new value, 6, but Circle is just getting "added 
on" to that result, and then stripped off again. There's a clear 
symmetry between construction and deconstruction which doesn't seem 
nearly as clear if Circle is seen as a function.

It occurs to me that when I talk about functions here, I am talking 
about Haskell function values, not about functions as equations "f(x) = 
...". In particular, one cannot write an invert :: (a->b) -> Maybe 
(b->a) which never returns a wrong answer, except for invert = const 
Nothing -- this is why it makes no sense to me to imagine Circle as 
being a Haskell *value*. I have no problem imagining it as a function in 
a more abstract mathematical sense; it's just that Haskell function 
values don't have that extra structure.

The view of Circle that I was trying to express is closer to Prolog 
clauses. One can assert circle(1.2), and that assertion will match 
circle(x), but it doesn't really make sense to assert circle, or to try 
to match it.

Have I succeeded in reconciling our views?

-- Ben



More information about the Haskell-Cafe mailing list