Trex record update strange rejection

Anthony Clayden <[email protected]> Fri, 9 Nov 2018 17:17:46 +1300
Newsgroups gmane.comp.lang.haskell.hugs.bugs
Message-ID <CAM7nRYQ-3x9j=cHPgBL_ruyKJn-4vHceW6wajsUMM==NM9Vm=w@mail.gmail.com>
--===============1232346997785307672==
Content-Type: multipart/alternative; boundary="000000000000da2f2d057a33a21e"

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

I'm trying to write a polymorphic/generic Trex record update method/class,
so I can go

> ... setTrex #y 7 r ...

That is: use #y to index into record `r`; return `r` with its `y` field set
to 7. Then it's using #y as a term-level proxy embedding the label, not as
an accessor function.
(If `r` does not contain a `y` field, that's a type error.)
This is potentially a type-changing update. (But I think that's not
relevant to the strangeness.)

So this is mimicking GHC's `SetField` class or Lenses. I'll use Lens-like
nomenclature.

> import Hugs.Trex
>
> class SetTrex s t a b  | s b -> t, s -> a  where
>   setTrex :: (Rec s -> a) -> b -> Rec s -> Rec t
>
> instance r'\y => SetTrex (y :: a | r') (y :: b | r') a b  where
>   setTrex _hashy y (y = _y | rho') = (y = y | rho')

Tediously, this will need an instance for each possible label name.

Tests

> setTrex #y 7 (y = 5)             -- returns (y = 7) -- OK
> setTrex #y 7 (z = 'z', y = 5)     -- returns (y = y, z = 'z')  -- OK
> setTrex #y 7 (x = 'x', y = 5)

ERROR - Constraints are not consistent with functional dependency

*** Constraint       : SetTrex (x :: Char, y :: a) (y :: b, x :: Char, y ::
b, x :: Char) a b

*** And constraint   : SetTrex (y :: a, x :: Char) (y :: b, x :: a) a b

*** For class        : SetTrex a b c d

*** Break dependency : d a -> b


(If I give an explicit signature for the result, the error goes away.)


Notice

* the complaint is about **constraints** not consistent

  so Hugs is generating constraints from the input expression

  and comparing to the constraint arising from the method's type


* the reversal in order of appearance of labels in the records.


* but chiefly, the weird doubling-up of the record fields in the first
Constraint.


If I try to update `y` in a record with 3 labels `x`, `y`, `z`, I get the
same error, with even more puzzling details.


( The type vars used in the 'For class .../dependency ...' are distinct
from the type vars in the constraints. That's usual Hugs perplexity.)

If I declare a direct function to achieve the same thing, with signature

> ss :: r'\y => (Rec (y :: a | r') -> a) -> b -> Rec (y :: a | r') -> Rec
(y :: b | r')
> ss _hashy y (y = _y | rho') = (y = y | rho')

all works fine. (But of course there's no FunDeps to worry about being
consistent with.)


AntC

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

<div dir=3D"auto">I&#39;m trying to write a polymorphic/generic Trex record=
 update method/class, so I can go</div><div dir=3D"auto"><br></div><div dir=
=3D"auto">&gt; ... setTrex #y 7 r ...</div><div dir=3D"auto"><br></div><div=
 dir=3D"auto">That is: use #y to index into record `r`; return `r` with its=
 `y` field set to 7. Then it&#39;s using #y as a term-level proxy embedding=
 the label, not as an accessor function.</div><div dir=3D"auto">(If `r` doe=
s not contain a `y` field, that&#39;s a type error.)</div><div dir=3D"auto"=
>This is potentially a type-changing update. (But I think that&#39;s not re=
levant to the strangeness.)</div><div dir=3D"auto"><br></div><div dir=3D"au=
to">So this is mimicking GHC&#39;s `SetField` class or Lenses. I&#39;ll use=
 Lens-like nomenclature.</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; class SetTrex s t a b =C2=A0| s b -&gt; t, s -&gt; a =C2=A0where</div><=
div dir=3D"auto">&gt; =C2=A0 setTrex :: (Rec s -&gt; a) -&gt; b -&gt; Rec s=
 -&gt; Rec t</div><div dir=3D"auto">&gt;</div><div dir=3D"auto">&gt; instan=
ce r&#39;\y =3D&gt; SetTrex (y :: a | r&#39;) (y :: b | r&#39;) a b =C2=A0w=
here</div><div dir=3D"auto">&gt; =C2=A0 setTrex _hashy y (y =3D _y | rho&#3=
9;) =3D (y =3D y | rho&#39;)</div><div dir=3D"auto"><br></div><div dir=3D"a=
uto">Tediously, this will need an instance for each possible label name.</d=
iv><div dir=3D"auto"><br></div><div dir=3D"auto">Tests</div><div dir=3D"aut=
o"><br></div><div dir=3D"auto">&gt; setTrex #y 7 (y =3D 5) =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 -- returns (y =3D 7) -- OK</div><div dir=3D"aut=
o">&gt; setTrex #y 7 (z =3D &#39;z&#39;, y =3D 5) =C2=A0 =C2=A0 -- returns =
(y =3D y, z =3D &#39;z&#39;) =C2=A0-- OK</div><div dir=3D"auto">&gt; setTre=
x #y 7 (x =3D &#39;x&#39;, y =3D 5)</div><div dir=3D"auto"><br></div><div d=
ir=3D"auto"><p style=3D"margin:0px;font-size:12px;line-height:normal;font-f=
amily:Helvetica"><span style=3D"font-size:12pt">ERROR - Constraints are not=
 consistent with functional dependency</span></p>
<p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helvet=
ica"><span style=3D"font-size:12pt">*** Constraint =C2=A0 =C2=A0 =C2=A0 : S=
etTrex (x :: Char, y :: a) (y :: b, x :: Char, y :: b, x :: Char) a b</span=
></p>
<p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helvet=
ica"><span style=3D"font-size:12pt">*** And constraint =C2=A0 : SetTrex (y =
:: a, x :: Char) (y :: b, x :: a) a b</span></p>
<p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helvet=
ica"><span style=3D"font-size:12pt">*** For class=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 : SetTrex a b c d</span></p>
<p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helvet=
ica"><span style=3D"font-size:12pt">*** Break dependency : d a -&gt; b</spa=
n></p><p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:=
Helvetica"><span style=3D"font-size:12pt"><br></span></p><p style=3D"margin=
:0px;font-size:12px;line-height:normal;font-family:Helvetica"><span style=
=3D"font-size:12pt">(If I give an explicit signature for the result, the er=
ror goes away.)</span></p><p style=3D"margin:0px;font-size:12px;line-height=
:normal;font-family:Helvetica"><span style=3D"font-size:12pt"><br></span></=
p><p style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helv=
etica"><span style=3D"font-size:12pt">Notice=C2=A0</span></p><p style=3D"ma=
rgin:0px;font-size:12px;line-height:normal;font-family:Helvetica"><span sty=
le=3D"font-size:12pt">* the complaint is about **constraints** not consiste=
nt</span></p><p style=3D"margin:0px;font-size:12px;line-height:normal;font-=
family:Helvetica"><span style=3D"font-size:12pt">=C2=A0 so Hugs is generati=
ng constraints from the input expression</span></p><p style=3D"margin:0px;f=
ont-size:12px;line-height:normal;font-family:Helvetica"><span style=3D"font=
-size:12pt">=C2=A0 and comparing to the constraint arising from the method&=
#39;s type</span></p><p style=3D"margin:0px;font-size:12px;line-height:norm=
al;font-family:Helvetica"><span style=3D"font-size:12pt"><br></span></p><p =
style=3D"margin:0px;font-size:12px;line-height:normal;font-family:Helvetica=
"><span style=3D"font-size:12pt">* the reversal in order of appearance of l=
abels in the records.</span></p><p style=3D"margin:0px;font-size:12px;line-=
height:normal;font-family:Helvetica"><span style=3D"font-size:12pt"><br></s=
pan></p><p style=3D"margin:0px;font-size:12px;line-height:normal;font-famil=
y:Helvetica"><span style=3D"font-size:12pt">* but chiefly, the weird doubli=
ng-up of the record fields in the first Constraint.</span></p><p style=3D"m=
argin:0px;font-size:12px;line-height:normal;font-family:Helvetica"><span st=
yle=3D"font-size:12pt"><br></span></p><p style=3D"margin:0px;font-size:12px=
;line-height:normal;font-family:Helvetica"><span style=3D"font-size:12pt">I=
f I try to update `y` in a record with 3 labels `x`, `y`, `z`, I get the sa=
me error, with even more puzzling details.</span></p><p style=3D"margin:0px=
;font-size:12px;line-height:normal;font-family:Helvetica"><span style=3D"fo=
nt-size:12pt"><br></span></p><p style=3D"margin:0px;font-size:12px;line-hei=
ght:normal;font-family:Helvetica"><span style=3D"font-size:12pt">( The type=
 vars used in the &#39;For class .../dependency ...&#39; are distinct from =
the type vars in the constraints. That&#39;s usual Hugs perplexity.)</span>=
</p><div dir=3D"auto"><span style=3D"font-size:12pt"><br></span></div><div =
dir=3D"auto"><span style=3D"font-size:12pt">If I declare a direct function =
to achieve the same thing, with signature</span></div><div dir=3D"auto"><sp=
an style=3D"font-size:12pt"><br></span></div><div dir=3D"auto"><span style=
=3D"font-size:12pt">&gt;=C2=A0</span><span style=3D"font-size:12pt;font-fam=
ily:Helvetica">ss :: r&#39;\y =3D&gt; (Rec (y :: a | r&#39;) -&gt; a) -&gt;=
 b -&gt; Rec (y :: a | r&#39;) -&gt; Rec (y :: b | r&#39;)</span></div><div=
 dir=3D"auto"><span style=3D"font-size:12pt;font-family:Helvetica">&gt;=C2=
=A0</span><span style=3D"font-size:12pt;font-family:Helvetica">ss _hashy y =
(y =3D _y | rho&#39;) =3D (y =3D y | rho&#39;) </span><span style=3D"font-s=
ize:12pt;font-family:Helvetica">=C2=A0</span></div><div dir=3D"auto"><span =
style=3D"font-size:12pt"><br></span></div><div dir=3D"auto"><span style=3D"=
font-size:12pt">all works fine. (But of course there&#39;s no FunDeps to wo=
rry about being consistent with.)</span></div><div dir=3D"auto"><span style=
=3D"font-size:12pt"><br></span></div><div dir=3D"auto"><span style=3D"font-=
size:12pt"><br></span></div><div dir=3D"auto"><span style=3D"font-size:12pt=
">AntC</span></div></div>

--000000000000da2f2d057a33a21e--

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

X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSHVncy1CdWdz
IG1haWxpbmcgbGlzdApIdWdzLUJ1Z3NAaGFza2VsbC5vcmcKaHR0cDovL21haWwuaGFza2VsbC5v
cmcvY2dpLWJpbi9tYWlsbWFuL2xpc3RpbmZvL2h1Z3MtYnVncwo=

--===============1232346997785307672==--