I am using Edward Kmett's lens library for the first time, and finding it rather nice, but I ran into a snag...
The question at [1] explains that existential quantifiers disrupt makeLenses. I really rather want to use an existential with lenses in some fashion.
As background, I have the class:
class (TextShow file, Eq file, Ord file, Typeable file) => File file where
fromAnyFile :: AnyFile -> Maybe file
fileType :: Simple Lens file FileType
path :: Simple Lens file Text.Text
provenance :: Simple Lens file Provenance
For the actual question, I want to have the type:
data AnyFile = forall file . File file => AnyFile { _anyFileAnyFile :: File }
And I want to be able to write something along the lines of:
instance File AnyFile where
fromAnyFile (AnyFile file) = cast file
fileType (AnyFile file) = fileType . anyFile
path (AnyFile file) = path . anyFile
provenance (AnyFile file) = provenance . anyFile
This doesn't work, for the reason explained in [1]. If I ask GHC for debugging information by compiling with -ddump-splices
, I get:
Haskell/Main.hs:1:1: Splicing declarations
makeLenses ''AnyFile ======> Haskell/Main.hs:59:1-20
The splice itself is blank, which indicates to me that no declarations are produced by it. This part I expect and understand now that I have read [1].
What I would like to know is how I can do this - what might I do to work around the problem? What might I do to avoid swimming upstream on this? I would like to be able to access any part of my structures through a path of composed lenses, but because I have fields in other types with types such as Set AnyFile
, I cannot do so unless I can access the content of AnyFile
with a lens.
[1] Existential quantifier silently disrupts Template Haskell (makeLenses). Why?
lens (\(AnyFile file) -> file) (\_ value -> AnyFile value)
. – Hinayana