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'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">> ... 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'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's a type error.)</div><div dir=3D"auto"= >This is potentially a type-changing update. (But I think that's not re= levant to the strangeness.)</div><div dir=3D"auto"><br></div><div dir=3D"au= to">So this is mimicking GHC's `SetField` class or Lenses. I'll use= Lens-like nomenclature.</div><div dir=3D"auto"><br></div><div dir=3D"auto"= >> import Hugs.Trex</div><div dir=3D"auto">></div><div dir=3D"auto">&= gt; class SetTrex s t a b =C2=A0| s b -> t, s -> a =C2=A0where</div><= div dir=3D"auto">> =C2=A0 setTrex :: (Rec s -> a) -> b -> Rec s= -> Rec t</div><div dir=3D"auto">></div><div dir=3D"auto">> instan= ce r'\y =3D> SetTrex (y :: a | r') (y :: b | r') a b =C2=A0w= here</div><div dir=3D"auto">> =C2=A0 setTrex _hashy y (y =3D _y | rho= 9;) =3D (y =3D y | rho')</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">> 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">> setTrex #y 7 (z =3D 'z', y =3D 5) =C2=A0 =C2=A0 -- returns = (y =3D y, z =3D 'z') =C2=A0-- OK</div><div dir=3D"auto">> setTre= x #y 7 (x =3D 'x', 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 -> 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 'For class .../dependency ...' are distinct from = the type vars in the constraints. That'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">>=C2=A0</span><span style=3D"font-size:12pt;font-fam= ily:Helvetica">ss :: r'\y =3D> (Rec (y :: a | r') -> a) ->= b -> Rec (y :: a | r') -> Rec (y :: b | r')</span></div><div= dir=3D"auto"><span style=3D"font-size:12pt;font-family:Helvetica">>=C2= =A0</span><span style=3D"font-size:12pt;font-family:Helvetica">ss _hashy y = (y =3D _y | rho') =3D (y =3D y | rho') </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'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==--