Trex label names: leaky abstraction

Anthony Clayden <[email protected]> Fri, 9 Nov 2018 15:42:40 +1300
Newsgroups gmane.comp.lang.haskell.hugs.user
Message-ID <CAM7nRYTkZCSc2oTatUiUkoQPGve1u4uyBQHatuzaUir5HvYWnQ@mail.gmail.com>
--===============5568109569661495194==
Content-Type: multipart/alternative; boundary="000000000000c10fc9057a324e48"

--000000000000c10fc9057a324e48
Content-Type: text/plain; charset="UTF-8"

Gaster & Jones 1996 says
"We consider two rows to be equivalent if they include the same fields
regardless of the order in which they are listed." [section 3.2]

But this is tricky: Figure 6 shows there is an ordering on labels, so that
in effect records are compiled to tuples with left-to-right ordering of
label names alphabetically.

The User Manual says
"The order of fields in a record pattern *is* significant because it
determines the order---from left to right---in which they are matched."
In particular, a pattern match on a record with a field value `undefined`
might succeed if some other field label is mentioned first in the pattern;
but throw an error if it's the undefined field's label mentioned first.

It's not difficult to expose this behaviour. Consider

> import Hugs.Trex
>
> x5y = (x = 5, y = 'y');   x7y = (x = 7, y = undefined)
> z5y = (z = 5, y = 'y');   z7y = (z = 7, y = undefined)
>
> x5y == x7y     -- returns False
> z5y == z7y     -- throws error Prelude.undefined

The tuples with label `z` are compiled to put that field second, regardless
of the order of appearing in the expression. Then (==) applies by comparing
field values in left-to-right alphabetic ordering. Field `x` is
alphabetically before `y`; and the `x` values differ; so the comparison
returns False without comparing the `y` values. Then in comparing the field
`z` records, the `y` fields are compared first (ignoring that the `z`
values differ), exposing that one `y` field is `undefined`.

This is similar to comparing tuples

> (5, 'y') == (7, undefined)   -- returns False
> ('y', 5) == (undefined, 7)   -- throws error

There seems to be some infelicity when building records:

> f ... rho ... = (y = 'y' | rho)

This throws strange errors depending whether `rho` includes labels that are
alphabetically before `y`. Bug report incoming ...


AntC

--000000000000c10fc9057a324e48
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"auto">Gaster &amp; Jones 1996 says</div><div dir=3D"auto">&quot=
;We consider two rows to be equivalent if they include the same fields rega=
rdless of the order in which they are listed.&quot; [section 3.2]</div><div=
 dir=3D"auto"><br></div><div dir=3D"auto">But this is tricky: Figure 6 show=
s there is an ordering on labels, so that in effect records are compiled to=
 tuples with left-to-right ordering of label names alphabetically.</div><di=
v dir=3D"auto"><br></div><div dir=3D"auto">The User Manual says</div><div d=
ir=3D"auto">&quot;<span style=3D"font-family:-webkit-standard;font-size:med=
ium;background-color:rgb(255,255,255)">The order of fields in a record patt=
ern=C2=A0</span><i style=3D"font-family:-webkit-standard">is</i><span style=
=3D"font-family:-webkit-standard;font-size:medium;background-color:rgb(255,=
255,255)">=C2=A0significant because it determines the order---from left to =
right---in which they are matched.</span>&quot;</div><div dir=3D"auto">In p=
articular, a pattern match on a record with a field value `undefined` might=
 succeed if some other field label is mentioned first in the pattern; but t=
hrow an error if it&#39;s the undefined field&#39;s label mentioned first.<=
/div><div dir=3D"auto"><br></div><div dir=3D"auto">It&#39;s not difficult t=
o expose this behaviour. Consider</div><div dir=3D"auto"><br></div><div dir=
=3D"auto">&gt; import Hugs.Trex</div><div dir=3D"auto">&gt;</div><div dir=
=3D"auto">&gt; x5y =3D (x =3D 5, y =3D &#39;y&#39;); =C2=A0 x7y =3D (x =3D =
7, y =3D undefined)</div><div dir=3D"auto">&gt; z5y =3D (z =3D 5, y =3D &#3=
9;y&#39;); =C2=A0 z7y =3D (z =3D 7, y =3D undefined)</div><div dir=3D"auto"=
>&gt;</div><div dir=3D"auto">&gt; x5y =3D=3D x7y =C2=A0 =C2=A0 -- returns F=
alse</div><div dir=3D"auto">&gt; z5y =3D=3D z7y =C2=A0 =C2=A0 -- throws err=
or Prelude.undefined</div><div dir=3D"auto"><br></div><div dir=3D"auto">The=
 tuples with label `z` are compiled to put that field second, regardless of=
 the order of appearing in the expression. Then (=3D=3D) applies by compari=
ng field values in left-to-right alphabetic ordering. Field `x` is alphabet=
ically before `y`; and the `x` values differ; so the comparison returns Fal=
se without comparing the `y` values. Then in comparing the field `z` record=
s, the `y` fields are compared first (ignoring that the `z` values differ),=
 exposing that one `y` field is `undefined`.</div><div dir=3D"auto"><br></d=
iv><div dir=3D"auto">This is similar to comparing tuples</div><div dir=3D"a=
uto"><br></div><div dir=3D"auto">&gt; (5, &#39;y&#39;) =3D=3D (7, undefined=
) =C2=A0 -- returns False</div><div dir=3D"auto">&gt; (&#39;y&#39;, 5) =3D=
=3D (undefined, 7) =C2=A0 -- throws error</div><div dir=3D"auto"><br></div>=
<div dir=3D"auto">There seems to be some infelicity when building records:<=
/div><div dir=3D"auto"><br></div><div dir=3D"auto">&gt; f ... rho ... =3D (=
y =3D &#39;y&#39; | rho)</div><div dir=3D"auto"><br></div><div dir=3D"auto"=
>This throws strange errors depending whether `rho` includes labels that ar=
e alphabetically before `y`. Bug report incoming ...</div><div dir=3D"auto"=
><br></div><div dir=3D"auto"><br></div><div dir=3D"auto">AntC</div>

--000000000000c10fc9057a324e48--

--===============5568109569661495194==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline

X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSHVncy1Vc2Vy
cyBtYWlsaW5nIGxpc3QKSHVncy1Vc2Vyc0BoYXNrZWxsLm9yZwpodHRwOi8vbWFpbC5oYXNrZWxs
Lm9yZy9jZ2ktYmluL21haWxtYW4vbGlzdGluZm8vaHVncy11c2Vycwo=

--===============5568109569661495194==--