我正在使用 lens 中的Select Product_ID,
sum(Unit_Price * On_Hand) as Product_Value
From Product_T
Group by Product_ID
Having sum(Unit_Price * On_Hand) >= 400.00
Order by sum(Unit_Price * On_Hand) desc;
生成为各种结构重载的字段。我想在具有多个结构的一个字段中使用这些字段,同时必须说明我只想使用一次哪个字段。它看起来像这样:
makeFields
我应该给{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
import Control.Lens
data A = A
{ _aX :: String
, _aY :: String
}
makeFields ''A
data B = B
{ _bX :: String -> Char
, _bY :: String -> Bool
}
makeFields ''B
-- x can get _aX from an A and _bX from a B
a :: A
a = undefined
b :: B
b = undefined
q :: (Getter A String) AND (Getter B (String -> a)) -> a
q lens = (b^.lens) (a^.lens)
哪种类型?我试过让GHC推断出类型,但那次失败了。
答案 0 :(得分:1)
要决定要做什么,我们需要知道您的(makeField
- 生成的)字段的类型:
GHCi> :t x
x :: (HasX s a, Functor f) => (a -> f a) -> s -> f s
所以覆盖所有x
- 承载类型的抽象(我在注意到你使用makeFields
之前抱怨的抽象)是一个多参数类型类HasX
,同样对于其他领域。这使我们足以在单个实现中使用不同类型的x
:
-- Additional extension required: FlexibleContexts
-- Note that GHC is able to infer this type.
qx :: (HasX t (a -> b), HasX s a) => t -> s -> b
qx t s = (t ^. x) (s ^. x)
GHCi> import Data.Maybe
GHCi> let testA = A "foo" "bar"
GHCi> let testB = B (fromMaybe 'ø' . listToMaybe) null
GHCi> qx testB testA
'f'
然而,这并不是你所要求的。你想要的东西是:
q xOrY b a = (b^.xOrY) (a^.xOrY)
然而,实现这一点需要对类 HasX
,HasY
等进行抽象。事实上,由于{{1}这样做,这样做有点可行。 }扩展,如Could we abstract over type classes?中所示,其中包含:
ConstraintKinds
-- Additional extensions required: ConstraintKinds, ScopedTypeVariables
-- Additional import required: Data.Proxy
-- GHC cannot infer this type.
q :: forall h s t a b. (h t (a -> b), h s a) => Proxy a -> Proxy h
-> (forall u c. h u c => Getting c u c) -> t -> s -> b
q _ _ l t s =
(t ^. (l :: Getting (a -> b) t (a -> b))) (s ^. (l :: Getting a s a))
确定中间类型的第一个代理是必要的,除非您放弃这一点通用性并将GHCi> q (Proxy :: Proxy String) (Proxy :: Proxy HasX) x testB testA
'f'
替换为a
。此外,您必须通过将getter作为参数和第二个代理传递两次来指定字段。我完全不相信第二种解决方案值得给我带来麻烦 - 必须定义String
,qx
等额外的样板看起来比这里所涉及的所有迂回都要痛苦得多。不过,如果你们这些正在阅读这篇文章的人想提出改进意见,那我就听见了。