4

我一直在阅读这篇文章以了解镜头。他们最初定义了一个类型同义词,如下所示:

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 Consta -> b呢?

4

2 回答 2

7

的类型r是通过将 const 仿函数替换为f; 因为我们需要一个b必须是第一个参数的结果(仅xConst x y类型中实际找到)

    r :: (b -> Const b b) -> (a -> Const b a)

现在论点很简单:那只是Const构造函数。

    r Const :: a -> Const b a

如果你用 post-compose getConst :: Const b a -> b,你最终会得到

    getConst . r Const :: a -> b
于 2014-04-07T12:02:21.473 回答
4

了解镜头类型的一种方法

type Lens s a = forall f . Functor f => (a -> f a) -> (s -> f s)

是将其读作“如果您告诉我如何将(重点)子部分放入某些Functor内容中,我可以告诉您如何将整个内容放入其中Functor”。但是,这forall意味着使用镜头的人可以选择Functor,所以我们可以玩花样。

Const Functor是一个技巧Functor,因为它有两个类型参数,但是当它Functor在第二个之上时……它实际上只包含第一个的值。

newtype Const real fake = Const { getConst :: real }

因此,构造函数Const是一个函数

Const :: real -> Const real fake

它隐藏了被包装的真实价值,并导致Functor假装携带任何类型fake


需要明确的是,该Functor实例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

换句话说,我们的 Lens 被欺骗将子部分 ,a注入Const并忽略了整体部分 , s。然后我们只需用getConst.

getConst :: Const real fake -> real

getConst . l Const :: s -> a
于 2014-04-07T14:04:27.213 回答