From anthony_clayden at clear.net.nz Fri Nov 9 04:17:46 2018 From: anthony_clayden at clear.net.nz (Anthony Clayden) Date: Fri, 9 Nov 2018 17:17:46 +1300 Subject: Trex record update strange rejection Message-ID: 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: