[Haskell-cafe] Newbie Question on type constructors
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?
More information about the Haskell-Cafe