带有约束的数据的makeLenses(DatatypeContexts)

时间:2015-03-18 23:07:31

标签: haskell lenses

我可以在带有约束的数据类型上使用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的初学者。)

1 个答案:

答案 0 :(得分:2)

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

{-# Language GADTs #-}

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

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

不幸的是,作为ØrjanJohansencommented,由于存在类型,你会立即自动制作镜片。但你应该,我相信能够手工编写它们,而数据类型上下文永远不会有效。