haskell 约束型镜片

wdebmtf2  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(204)

假设我有

getXY :: X a -> Y a
setXY :: C a => X a -> Y a -> X a

有没有可能写一些像镜头一样的东西,只在设置时施加C a?我对货车Laarhoven和profunctor风格的光学都很感兴趣。

m1m5dgzv

m1m5dgzv1#

我不能肯定,但就你给的那些类型,我看不出有什么办法。
也就是说,您是否对类型进行了过度限制?setXY是否可能被允许具有以下类型:

setXY :: C b => X a -> Y b -> X b

换句话说,约束C对第二个参数和输出很重要,但对输入不重要。如果是这样,那么你 * 可以 * 制作下面的透镜:

lensXY :: C b => Lens (X a) (X b) (Y a) (Y b)
lensXT = lens getXY setXY

这仍然是一个有点奇怪的透镜。例如,假设你有一个x :: X Int类型的值,但是Int不是C的示例。那么,如果你尝试x ^. lensXY,你会得到一个错误。有趣的是,这不是镜头的缺陷,而是^.的缺陷,它有一个过度限制的类型。
现在考虑一下,如果我们将^.重新定义为:

(^.) :: s -> Lens s t a b -> a
s ^. l = getConst (l Const s)

请注意,函数定义与前面的定义完全相同,但我们更改了类型签名(它对镜头更通用,但对其他东西更有约束)。现在,我们 * 几乎 * 可以执行x ^. lensXY,但现在的问题是GHC不知道tb使用什么类型。具体来说,它需要一个满足C约束的类型。然后,我们可以写x ^. lensXY @Bool,它进行类型检查并提取Y a的值,即使a不是C的示例。
另一方面,使用%~或类似的方法仍然需要类约束。

相关问题