没有模板haskell的多形态镜头

yil*_*yin 2 polymorphism haskell haskell-lens

我试图为多种类型创建一个多态镜头decleration(没有模板haskell).

module Sample where
import Control.Lens
data A = A {_value:: Int}
data B = B {_value:: Int}
data C = C {_value:: String}
value = lens _value (\i x -> i{_value=x}) -- <<< ERROR
Run Code Online (Sandbox Code Playgroud)

但我得到以下错误:

Ambiguous occurrence ‘_value’
It could refer to either the field ‘_value’,
                         defined at library/Sample.hs:5:13
                      or the field ‘_value’, defined at 
library/Sample.hs:4:13
                      or the field ‘_value’, defined at 
library/Sample.hs:3:13
  |
6 | value = lens _value (\i x -> i{_value=x}) -- <<< ERROR
  |              ^^^^^^
Run Code Online (Sandbox Code Playgroud)

因此,目标是让value镜头在所有三种类型A,B和C上工作.有没有办法实现这一目标?谢谢.

Li-*_*Xia 8

通用透镜可以在没有TH的情况下导出透镜.您可以将通用field镜头专门用于特定领域,并为其命名如下.

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeApplications #-}

import GHC.Generics (Generic)
import Control.Lens (Lens, (^.))
import Data.Generics.Product (HasField(field))

data A = A { _value :: Int } deriving Generic
data B = B { _value :: Int } deriving Generic
data C = C { _value :: String } deriving Generic

value :: HasField "_value" s t a b => Lens s t a b
value = field @"_value"

main :: IO ()
main = print (A 0 ^. value, B 0 ^. value, C "0" ^. value)
Run Code Online (Sandbox Code Playgroud)