How to get classy lenses with overloaded field names?

扶醉桌前 提交于 2019-12-06 02:14:13
András Kovács

Use makeFields from Control.Lens.TH:

{-# language
  TemplateHaskell, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}

import Control.Lens

data Bar a n = Bar {
  _barAge :: a,
  _barName :: n
} deriving Show

data Foo = Foo {
  _fooAge  :: Int,
  _fooName :: String
} deriving Show

makeFields ''Bar
makeFields ''Foo

Now you have the following classes:

class HasName s a | s -> a where
  name :: Lens' s a

class HasAge s a | s -> a where
  age :: Lens' s a

and the appropriate instances for Foo and Bar. Example:

> Foo 10 "foo" ^. age
10
> Bar 10 "bar" ^. age
10

You can then implement the classes for wrapper objects. Example:

data FooWrapper = FooWrapper {
  _fooWrapperKey :: Int,
  _fooWrapperFoo :: Foo
} deriving Show

makeFields ''FooWrapper

instance HasName FooWrapper String where
  name = foo . name

instance HasAge FooWrapper Int where
  age = foo . age
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!