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)
?
答案 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)
fromGetting
和toGetting
都没有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
为什么这相当于f
? forall
是关键所在:
f :: forall r. Getting r s a
-- forall r. (a -> r) -> s -> r
f
无法生成r
,除非将传递的函数(让我们称之为p
)应用于类型a
的值。除了p
和s
类型的值之外,它什么都没有给出。因此f
除了从a
中提取s
并将p
应用于结果外,其他任何事情都无法做任何事情。也就是说,f p
必须"因素"进入两个功能的组成:
f p = p . h
所以
g . f id = g . (id . h) = g . h = f g
答案 1 :(得分:1)
该类型显示“你给我b -> b
和a
,我会给你一个b
。”具有该类型的函数可以使用b -> b
做什么?两个选项:
b
如何获得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)