我一直在阅读this post以了解镜头。他们最初定义了一个 类似这样的同义词:
type RefF a b = forall f. Functor f => (b -> f b) -> (a -> f a)
Const的定义如下:
newtype Const a b = Const { getConst :: a }
get
函数类型检查如何:
get :: RefF a b -> a -> b
get r = getConst . r Const
getConst的类型是这样的:
getConst :: Const a b -> a
我猜的r Const
的类型是这样的:
r Const = (b -> f b) -> (Const -> f Const)
那么,getConst
和r Const
如何组合以提供a -> b
?
答案 0 :(得分:8)
r
的类型是通过用const仿函数代替f
获得的;因为我们需要b
结果必须是第一个参数(x
类型中实际只找到Const x y
)
r :: (b -> Const b b) -> (a -> Const b a)
现在论证很简单:那只是Const
构造函数。
r Const :: a -> Const b a
如果您使用getConst :: Const b a -> b
进行后期撰写,则最终会使用
getConst . r Const :: a -> b
答案 1 :(得分:4)
了解镜头类型的一种方法
type Lens s a = forall f . Functor f => (a -> f a) -> (s -> f s)
将其读作“如果你告诉我如何将(重点)子部分放入某些Functor
我可以告诉你如何将整个事物放入Functor
”。 forall
意味着使用镜头的人可以选择Functor
,所以我们可以玩弄技巧。
Const
Functor
是一个技巧Functor
,因为它有两个类型参数,但它是Functor
ial而不是第二个...它实际上只包含第一个值。
newtype Const real fake = Const { getConst :: real }
因此,构造函数Const
是一个函数
Const :: real -> Const real fake
它会隐藏被包裹的真实价值,并导致Functor
假装携带任何类型的fake
。
要明确的是,Functor
的{{1}}实例看起来像
Const
换句话说,instance Functor (Const b) where
fmap _ (Const b) = Const b
本质上是一种无操作。
让我们看看当我们将fmap
传递给镜头时会发生什么:
Const
换句话说,我们的镜头被诱骗将子部分l :: Lens s a
Const :: a -> Const a a
l Const :: s -> Const a s
注入a
并忽略整个部分Const
。然后我们只用s
提取它。
getConst