Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use setter with polymorphic type?

How to use lens (setter) in this case?

Module A:

data Xxx a = Xxx {
    _xxxAaa :: Int,
    _xxxBbb :: a
}
makeFields ''Xxx

Module B:

t :: IO Bool
t = do
    let n = "aaa" :: String
    let xs = [Xxx 0 0, Xxx 1 1] :: [Xxx Int]
        ys = [set bbb n $ x | x <- xs]
    pure False

Error is:

• Couldn't match type ‘Int’ with ‘[Char]’
    arising from a functional dependency between:
      constraint ‘HasBbb (Xxx Int) String’ arising from a use of ‘bbb’
      instance ‘HasBbb (Xxx a) a’
        at .........

Btw, this trick works with tuples (they are polymorphic too), but not with such type.

like image 811
RandomB Avatar asked Nov 30 '25 20:11

RandomB


1 Answers

The HasBbb class generated by makeFields does not offer a type changing lens:

ghci> :i HasBbb
class HasBbb s a | s -> a where
  bbb :: Lens' s a
  {-# MINIMAL bbb #-}
        -- Defined at A.hs:14:1
instance HasBbb (Xxx a) a -- Defined at A.hs:14:1

Contrast it with the Xxx-specific lens generated by makeLenses:

data Xxx a = Xxx {
    _xxxAaa :: Int,
    _xxxBbb :: a
}
makeFields ''Xxx
makeLenses ''Xxx
ghci> :i xxxBbb
xxxBbb :: Lens (Xxx a1) (Xxx a2) a1 a2  -- Defined at A.hs:15:1
ghci> :t set xxxBbb "aaa" (Xxx 0 0)
set xxxBbb "aaa" (Xxx 0 0) :: Xxx [Char]
like image 170
duplode Avatar answered Dec 03 '25 13:12

duplode



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!