makeLenses 对具有约束的数据 (DatatypeContexts)

makeLenses on data with constraint (DatatypeContexts)

我可以在具有约束的数据类型上使用 makeLenses 模板吗?如果可以,如何使用?我想在不阅读所有关于 Template Haskell.

的情况下这样做

在 GHC 中我有这个例子:

{-# LANGUAGE TemplateHaskell, FlexibleInstances, UndecidableInstances, NoMonomorphismRestriction #-}
module Main (main) where

import Control.Lens
import Control.Monad.Reader  -- mtl

class Class1 a where
    someThing :: a  -- just some filler

instance (Num a) => Class1 a where
    someThing = 3

data (Class1 a) => Foo a = Foo { _field1 :: a }

makeLenses ''Foo

main :: IO ()
main = putStrLn . show $ runReader (view field1) $ Foo { _field1 = 5 }

这会产生此编译错误:

Could not deduce (Num a1) arising from a use of ‘Foo’
from the context (Profunctor p, Functor f)
  bound by the type signature for
             field1 :: (Profunctor p, Functor f) =>
                       p a (f a1) -> p (Foo a) (f (Foo a1))
  at src/main.hs:58:1-16
Possible fix:
  add (Num a1) to the context of
    the type signature for
      field1 :: (Profunctor p, Functor f) =>
                p a (f a1) -> p (Foo a) (f (Foo a1))
In the second argument of ‘iso’, namely ‘Foo’
In the expression: iso (\ (Foo x_a3NK) -> x_a3NK) Foo
In an equation for ‘field1’:
    field1 = iso (\ (Foo x_a3NK) -> x_a3NK) Foo

所以我认为它产生了:

field1 :: Lens' (Foo a) a

我也试过 makeFieldsmakeClassy,但没有用。

我知道我可以解决这个问题:

field1 :: (Class1 a) => Lens' (Foo a) a
field1 = lens _field1 (\ foo val -> Foo { _field1 = val })

但是有没有办法用 makeLenses 或模板 Haskell 来做到这一点?

我使用的是 GHC 7.8.4 版和 lens 4.8 版。

(注意:我知道有关于 makeLenses 的类似问题,但我仍然无法让它工作。我是 haskell 的初学者。)

我认为,问题在于数据类型上下文是一个有点破损的功能。您可能想使用 GADT:

{-# Language GADTs #-}

data Foo a where
  Foo :: Class1 a => a -> Foo a

我不确定如何使用 class 约束获取记录语法。

不幸的是,作为 Ørjan Johansen ,您将立即 运行 由于存在类型而陷入自动制作镜头的麻烦。但是我相信你应该能够手写它们,而数据类型上下文永远不会起作用。