> Why Haskell is so? Why case zipRem undefined []
> of
> (ps,xs',ys') -> ((x,y):ps, xs', ys')
>
> does not allow the result of zipRem undefined []
> to be of (ps,xs',ys')
> (which type is declared in zipRem) ?
> And `let', `where' do allow this.
>
> Now, the simpler example:
> f [] = []
> f (x:xs) = case f xs of ps -> (x,x):ps
>
> head $ f (1:undefined) --> (1,1)
>
> Here `case' behaves differently. I am about totally confused.
> The past century was not enough to study the basic Haskell.
> Maybe, the constructor (,,) in the zipRem pattern forces some kind
> of strictness, I do not know.
This is a consequence of the semantics of pattern matching (consult the
Haskell Report). EVERY type in Haskell has _|_ (bottom = undefined;
think
about this definition: x=x) as one of its elements, including the tuple
types (([a],[a],[a]), for example). But when you ask in a case
expression
that certain expression e SHOULD have the form (ps,xs',ys'), the
compiler
should COMPUTE e until it founds the tuple constructor; as the rule to
compute bottom is x=x, then that computation is also undefined. That's
for
let undef = undef
in case undef of
(ps,xs',ys') -> 1:ps
~
_|_
In the simpler case of case e of ps -> ..., the variable ps always
succeed, and then
let undef = undef
in case undef of
ps -> 1:ps
~
1:undef
If you change the cases by wheres, as in
f = 1:ps
where (ps,xs',ys') = undef
the where part is not computed UNTIL you need ps, and then f is
equivalent to 1:undef. The case expression FORCES the computation of e,
while the where does not (let neither).
It's clear now?
Fidel.