具有总和类型的镜头(具有产品类型)

时间:2016-04-19 20:41:55

标签: haskell lens

{-# LANGUAGE TemplateHaskell      #-}

import Control.Lens

data Fruit = Fruit
  { _fruitColor :: String
  }

$(makeClassy ''Fruit)

data Fruits =
    Banana Int Fruit
  | Strawberry String Fruit

printer :: HasFruit s => s -> IO ()
printer f = putStrLn $ f ^. fruitColor

sample :: IO ()
sample = do
  printer $ Fruit "yellow"
  printer $ Banana 5 $ Fruit "yellow"

我有一个核心产品类型,Fruit。我希望数据类型都包含核心产品类型Fruit,但希望能够用sum类型Fruit表示它们。使用和类型Fruits,我希望能够访问核心产品类型Fruit的组件。也就是说,我喜欢像香蕉和草莓这样的类型是HasFruit的一个例子。

有没有直接的方法让Fruits实例化HasFruit?是否有更好的模式来表示这一点 - 总和类型的核心产品类型?

1 个答案:

答案 0 :(得分:1)

做这样的事情会更有意义:

data FruitType = Banana Int | Strawberry String

data Fruits = Fruits { _fruitsFruitType :: FruitType, _fruitsFruit :: Fruit }

makeFields ''Fruits

-- `Fruits` now instantiates `HasFruit`

您可能还想为FruitType制作棱镜。棱镜基本上是遍历总和类型的不同部分,除了它们也可用于构造它。

makePrisms ''FruitType

-- double the int if the argument is a `Banana`

doubleBanana = fruitType._Banana *~ 2