我可以在带有约束的数据类型上使用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
我也尝试了makeFields
和makeClassy
,但无济于事。
我知道我可以解决这个问题:
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的初学者。)
答案 0 :(得分:2)
我认为,问题在于数据类型上下文是一个有点破碎的功能。你可能想要使用GADT:
{-# Language GADTs #-}
data Foo a where
Foo :: Class1 a => a -> Foo a
我不确定如何使用类约束来获取记录语法。
不幸的是,作为ØrjanJohansencommented,由于存在类型,你会立即自动制作镜片。但你应该,我相信能够手工编写它们,而数据类型上下文永远不会有效。