idris - 使用达到一定等价的类型
问题描述
假设我们想将(有符号)整数表示为自然数上的 Grothendieck 群(或者,换句话说,作为一对(m, n)
,其中可以理解的整数是m - n
):
data ZTy : Type where
MkZ : (m, n : Nat) -> ZTy
现在,语言免费提供给我们的(结构)等式不再是我们想要的:相反,我们只关心某种等价关系(即(m1, n1) ~ (m2, n2)
iff m1 + n2 = m2 + n1
)。废话不多说,写一下吧!
data Equiv : ZTy -> ZTy -> Type where
MkEquiv : (prf : m1 + n2 = m2 + n1) -> Equiv (MkZ m1 n1) (MkZ m2 n2)
但是处理这个问题很快就会变得一团糟。任何类型prop Const
(for prop : ZTy -> Type
) 的参数都被替换为(k : ZTy) -> (k `EqZ` Const) -> prop k
,至少可以说(作为一个更应用的例子,我正在努力写下这种类型的双面归纳证明,我仍然不确定我是否得到了该期限权利的签名)。
此外,replaceZ : {P : ZTy -> Type} -> (k1 `Equiv` k2) -> P k1 -> P k2
(显然)这样的功能不存在,但我找不到更好的候选人。作为一个有趣的旁注/观察,如果我们不导出 的定义ZTy
,则没有客户端代码P
可以观察到它,并且此函数对于任何其他模块中定义的任何内容都有意义,P
但看起来我们无法在语言中内化它.
我想到的另一件事是将谓词集限制为在等价关系下成立的谓词。也就是说,用诸如where之P : ZTy -> Type
类的东西代替,在等价关系下证明其不变性:P : ZTy -> Type, pAdmissible : ZPred P
ZPred
data ZPred : Type -> Type where
MkZPred : {P : ZTy -> Type} ->
(preservesEquiv : {k1, k2 : ZTy} -> (k1 `Equiv` k2) -> P k1 -> P k2) ->
ZPred P
无论如何,使用这些类型的常用方法是什么?还有什么可以很好地工作的吗?
我也听说过一些关于商类型的东西,但我不太了解。
解决方案
Coq 使用丰富的“关系组合器”语言来描述这些情况,这是您上一个想法的更好版本。我会翻译它。你有
ZTy : Type -- as yours
然后您继续在关系上定义关系和函数:
-- if r : Relation t and x, y : t, we say x and y are related by r iff r x y is inhabited
Relation : Type -> Type
Relation t = t -> t -> Type
-- if x, y : ZTy, we say x and y are (Equiv)alent iff Equiv x y is inhabited, etc.
Equiv : Relation ZTy -- as yours
(=) : Relation a -- standard
Iso : Relation Type -- standard
-- f and f' are related by a ==> r if arguments related by a end up related by r
(==>) : Relation a -> Relation b -> Relation (a -> b)
(==>) xr fxr = \f, f' => (x x' : a) -> xr x x' -> fxr (f x) (f' x')
infixr 10 ==>
这个想法是Equiv
,(=)
和Iso
都是平等的关系。Equiv
和(=)
是两个不同的相等概念ZTy
,(=)
和Iso
是两个相等的概念Type
。(==>)
将关系组合成新的关系。
如果你有
P : ZTy -> Type
您想说的是,Equiv
alent 参数映射到Iso
形态类型。也就是说,你需要
replaceP : (x x' : ZTy) -> Equiv x x' -> Iso (P x) (P x')
关系语言如何提供帮助?好吧,replaceP
本质上是在关系下说它P
与自身“相等” Equiv ==> Iso
(NBEquiv ==> Iso
不是等价,但它唯一缺少的是自反性。)如果一个函数在 下与自身不“相等” Equiv ==> Iso
,那就有点就像一个“矛盾”,而那个功能在你的宇宙中“不存在”。或者,如果你想写一个函数
f : (ZTy -> Type) -> ?whatever
您可以通过要求这样的证明参数来限制自己使用正确类型的函数
Proper : Relation a -> a -> Type
Proper r x = r x x
f : (P : ZTy -> Type) -> Proper (Equiv ==> Iso) P -> ?whatever
但是,通常情况下,除非绝对需要,否则您会省略证明。事实上,标准库已经包含了很多关于 的函数ZTy
,比如
concatMap : Monoid m => (ZTy -> m) -> List ZTy -> m
而不是写一个concatMap
接受证明的论点,你真的只需要写一个关于 的证明concatMap
:
concatMapProper : Proper ((Equiv ==> (=)) ==> Pairwise Equiv ==> (=))
-- you'd really abstract over Equiv and (=), but then you need classes for Relations
Pairwise : Relation a -> Relation [a] -- as you may guess
我不确定你想写什么归纳原理,所以我就不说了。但是,您担心的是
proof : Property Constant
总是需要替换为
proof : (k : ZTy) -> Equiv k Constant -> Property k
只是部分有根据。如果你已经有
PropertyProper : Proper (Equiv ==> Iso) Property
您很可能应该这样做,然后您可以编写,并在需要时将其proper : Property Constant
推入通用化。(或者,通过使用顶部的简单定义来PropertyProper
编写一般签名)。但是,您不能在某处写证明,因为它根本不是那么微不足道。proper
PropertyProper
还值得注意的是,(==>)
除了作为Proper
. 它用作通用的外延等式:
abs1 : ZTy -> Nat
abs1 (MkZ l r) = go l r
where go (S n) (S m) = go n m
go Z m = m
go n Z = n
abs2 : ZTy -> Nat
abs2 (MkZ l r) = max l r - min l r
absEq : (Equiv ==> (=)) abs1 abs2
-- : (x x' : ZTy) -> Equiv x x' -> abs1 x = abs2 x'
推荐阅读
- c# - 代码生成 - 生成类,其接口引用生成类的嵌套类型
- python - Creating Search function on CSV file through flask
- javascript - 如何在 ajax 中呈现作为 Flask 应用程序响应发送的模板?
- javascript - UnhandledPromiseRejectionWarning: Error: Evaluation failed: ReferenceError: k is not defined
- google-app-engine - Unexpected Error when deploying google cloud function
- android - Android App kiosk mode on fully managed Chromebook
- terminal - How to set $PATH variable in Spyder console equal to $PATH in terminal?
- google-cloud-vertex-ai - google's notebook on vertex ai throwing following error: type name google.VertexModel is different from expected: Model
- hashicorp-vault - Is there a way to change the RAFT leader in vaul?
- java - How to calculate xlsx columns width from page coordinates?