假设我有
getXY :: X a -> Y a setXY :: C a => X a -> Y a -> X a
有没有可能写一些像镜头一样的东西,只在设置时施加C a?我对货车Laarhoven和profunctor风格的光学都很感兴趣。
C a
m1m5dgzv1#
我不能肯定,但就你给的那些类型,我看不出有什么办法。也就是说,您是否对类型进行了过度限制?setXY是否可能被允许具有以下类型:
setXY
setXY :: C b => X a -> Y b -> X b
换句话说,约束C对第二个参数和输出很重要,但对输入不重要。如果是这样,那么你 * 可以 * 制作下面的透镜:
C
lensXY :: C b => Lens (X a) (X b) (Y a) (Y b) lensXT = lens getXY setXY
这仍然是一个有点奇怪的透镜。例如,假设你有一个x :: X Int类型的值,但是Int不是C的示例。那么,如果你尝试x ^. lensXY,你会得到一个错误。有趣的是,这不是镜头的缺陷,而是^.的缺陷,它有一个过度限制的类型。现在考虑一下,如果我们将^.重新定义为:
x :: X Int
Int
x ^. lensXY
^.
(^.) :: s -> Lens s t a b -> a s ^. l = getConst (l Const s)
请注意,函数定义与前面的定义完全相同,但我们更改了类型签名(它对镜头更通用,但对其他东西更有约束)。现在,我们 * 几乎 * 可以执行x ^. lensXY,但现在的问题是GHC不知道t和b使用什么类型。具体来说,它需要一个满足C约束的类型。然后,我们可以写x ^. lensXY @Bool,它进行类型检查并提取Y a的值,即使a不是C的示例。另一方面,使用%~或类似的方法仍然需要类约束。
t
b
x ^. lensXY @Bool
Y a
a
%~
1条答案
按热度按时间m1m5dgzv1#
我不能肯定,但就你给的那些类型,我看不出有什么办法。
也就是说,您是否对类型进行了过度限制?
setXY
是否可能被允许具有以下类型:换句话说,约束
C
对第二个参数和输出很重要,但对输入不重要。如果是这样,那么你 * 可以 * 制作下面的透镜:这仍然是一个有点奇怪的透镜。例如,假设你有一个
x :: X Int
类型的值,但是Int
不是C
的示例。那么,如果你尝试x ^. lensXY
,你会得到一个错误。有趣的是,这不是镜头的缺陷,而是^.
的缺陷,它有一个过度限制的类型。现在考虑一下,如果我们将
^.
重新定义为:请注意,函数定义与前面的定义完全相同,但我们更改了类型签名(它对镜头更通用,但对其他东西更有约束)。现在,我们 * 几乎 * 可以执行
x ^. lensXY
,但现在的问题是GHC不知道t
和b
使用什么类型。具体来说,它需要一个满足C
约束的类型。然后,我们可以写x ^. lensXY @Bool
,它进行类型检查并提取Y a
的值,即使a
不是C
的示例。另一方面,使用
%~
或类似的方法仍然需要类约束。