证明在Haskell镜头库中断言的类型等价性

时间:2017-05-19 19:26:22

标签: haskell lens

根据tutorial on Lenses

type Getting b a b  = (b -> Const b b) -> (a -> Const b a)

-- ... equivalent to: (b ->       b  ) -> (a ->       b  )

-- ... equivalent to:                     (a ->       b  )

问题:为什么(b -> b) -> (a -> b)等同于(a -> b)

2 个答案:

答案 0 :(得分:10)

本教程对此并不十分准确。这是Getting的完整定义:

type Getting r s a = (a -> Const r a) -> s -> Const r s

剥离newtype噪音,

Getting r s a ~= (a -> r) -> s -> r

你应该从中获得有趣的同构如下:

(forall r. Getting r s a) ~= s -> a

在一条现已删除的评论中,chi指出这是Yoneda lemma的一个特例。

见证了同构
fromGetting :: Getting a s a -> (s -> a)
fromGetting g = getConst . g Const
           -- ~= g id

-- Note that the type of fromGetting is a harmless generalization of
-- fromGetting :: (forall r. Getting r s a) -> (s -> a)

toGetting :: (s -> a) -> Getting r s a
toGetting f g = Const . getConst . g . f
           -- ~= g . f

-- Note that you can read the signature of toGetting as
-- toGetting :: (s -> a) -> (forall r. Getting r s a)

fromGettingtoGetting都没有Rank-2类型,但描述同构,forall是必不可少的。为什么这是同构??

一方面很容易:忽略Const噪音,

  fromGetting (toGetting f)
= toGetting f id
= id . f
= f

另一方比较棘手。

  toGetting (fromGetting f)
= toGetting (f id)
= \g -> toGetting (f id) g
= \g -> g . f id

为什么这相当于fforall是关键所在:

f :: forall r. Getting r s a
  -- forall r. (a -> r) -> s -> r

f无法生成r,除非将传递的函数(让我们称之为p)应用于类型a的值。除了ps类型的值之外,它什么都没有给出。因此f除了从a中提取s并将p应用于结果外,其他任何事情都无法做任何事情。也就是说,f p必须"因素"进入两个功能的组成:

f p = p . h

所以

g . f id = g . (id . h) = g . h = f g

答案 1 :(得分:1)

该类型显示“你给我b -> ba,我会给你一个b。”具有该类型的函数可以使用b -> b做什么?两个选项:

  1. 完全忽略该功能
  2. 将其应用于b
  3. 如何获得b来应用该功能?您使用a生成一个。无论哪种方式,它都必须完成a -> b的工作。

    这是一些见证(编辑:不完全)同构的代码。

    in :: ((b -> b) -> a -> b) -> (a -> b)
    in f x = f id x
    
    out :: (a -> b) -> ((b -> b) -> a -> b)
    out f g x = g (f x)