首页 > 解决方案 > 如何使用多态类型的setter?

问题描述

在这种情况下如何使用镜头(设置器)?

模块 A:

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

模块 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

错误是:

• 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 .........

顺便说一句,这个技巧适用于元组(它们也是多态的),但不适用于这种类型。

标签: haskellhaskell-lens

解决方案


HasBbb生成的类makeFields不提供类型更改镜头:

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

Xxx将其与- 生成的特定镜头进行对比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]

推荐阅读