如何思考法律缺失

时间:2018-06-24 17:07:46

标签: haskell math types

我是一位从事类别理论工作的数学家,并且我已经使用Haskell进行了一段时间的计算等工作,但是我绝对不是程序员。我真的很喜欢Haskell,并且希望变得更加流利,而在编写程序时,我发现类型系统是非常有用的。

但是,我最近一直在尝试实现类别理论的东西,并且遇到了一个问题,即您似乎在Haskell中没有类方法法则。如果我的术语是错误的,我的意思是我可以写

class Monoid c where
    id :: c -> c
    m :: c -> c -> c

但是我不能写一些定律

m (m x y) z ==  m x $ m y z

根据我的收集,这是由于Haskell中缺少依赖类型,但是我不确定情况到底是什么(现在已经阅读了一些有关依赖类型的信息)。似乎惯例也只是在评论中包括这样的法律,并希望您不要偶然制作一些令其不满意的实例。

  1. 我应该如何改变对Haskell的处理方式?是否有一个很好的数学/类型理论解决方案(例如,要求存在一个同构的关联器(尽管问题是,如何在没有定律的情况下对同构进行编码?));是否存在一些“ hack”(使用诸如DataKinds之类的扩展名);我是否应该大刀阔斧地转而使用Idris之类的东西;还是对改变我使用Haskell的思维方式的最佳回应(即接受这些法律不能以Haskelly的方式实施)?
  2. (奖励)缺乏法律的确切原因是不支持依存类型?

1 个答案:

答案 0 :(得分:7)

[请注意,堆栈溢出不支持mathjax,但是您似乎已经完成了数学学位,所以我假设您可以阅读它]

您要这样:

m (m x y) z = m x (m y z)        -- (1)

但是要要求这样做,您需要一种检查方法。因此,您或您的编译器(或证明助手)需要构造此证明。问题是(1)的证明是什么类型?

一个人可以想象一些Proof类型,但是也许您可以构造一个证明0 = 0而不是(1)证明,并且两者都具有类型Proof。因此,您需要一个更通用的类型。我无法决定如何分解其余问题,因此我将对Curry-Howard同构进行简要说明,然后说明如何证明两件事相等,然后说明依存类型如何相关。


Curry-Howard同构说,命题与类型同构,证明与程序同构:类型对应于一个命题,该命题的证明对应于构造一个居住该类型的值的程序。忽略将多少类型表示为类型,一个例子是类型A * B(在Haskell中写为(A, B))对应于命题“ AB”,而类型A + B(在Haskell中写为Either A B)对应于命题“ AB”。最后,类型A -> B对应于“ {{1} }暗示A,”作为对此的证明,是一个程序收集了B的证据并为您提供了A的证据。应该注意的是,没有一种表达B的方法,但是可以想象添加一个类型为not A的内置Not A的类型Either a (Not a)来排除中间律和{{ 1}}和Not (Not a) -> a(其中a * Not a -> Void是一种无法居住的类型,因此对应于false),但是这样一来,您就无法真正运行这些程序来获取构造主义证明。

现在,我们将忽略Haskell的某些现实情况,并想象没有办法绕过这些规则(特别是Void表示一切都是真实的,undefined :: a则表示任何事物都暗示着其他任何事物,或者仅仅是其他在其存在并不暗示相应证据的地方不返回的函数。

所以我们知道如何组合命题,但是命题可能是什么?好吧,可以说两种类型是相等的。在Haskell中,这对应于GADT

unsafeCoerce :: a -> b

此构造函数对应于相等的反射性属性。

[旁注:如果到目前为止您仍然很感兴趣,那么您可能有兴趣查找Voevodsky的单价基础,具体取决于您对“同型类型理论”的想法是否感兴趣]

那么我们现在可以证明一些东西吗?平等的传递性如何?

data Eq a b where Refl :: Eq c c

感觉好像还没有真正证明任何东西(特别是因为这主要取决于编译器知道传递和对称属性),但是在证明逻辑上的简单事物时也会有类似的感觉。


那么现在您如何证明原始命题(1)?好吧,让我们想象一下,我们希望类型trans :: Eq a b -> Eq b c -> Eq a c trans x y = case x of Refl -> -- by this match being successful, the compiler now knows that a = b case y of Refl -> -- and now b = c and so the compiler knows a = c Refl -- the compiler knows that this is of type Eq d d, and as it knows a = c, this typechecks as Eq a c 是一个类半群,然后我们还应该证明$ \ forall x,y,z:c,m(mxy)z = mx(myz)。$因此,我们需要一种方法将c表示为一种类型。严格来说,这不是依赖类型(可以使用m (m x y) z来提升值和类型族而不是函数)。但是您确实需要依赖类型,以使类型依赖于值。具体来说,如果您具有自然数类型DataKinds和类型族NatVec :: Nat -> *是所有类型的类型(读取类型))固定长度向量,则可以定义一个从属变量类型函数*。观察输出的类型如何取决于输入的 value

因此,您的法律需要将功能提升到类型级别(跳过有关如何定义类型相等和值相等的问题),以及从属类型(组成语法):

mkVec :: (n::Nat) -> Vec n

观察从属类型和证明类型如何趋于庞大。在缺少类型类的语言中,可以将这样的值放入记录中。


关于依赖类型理论的最后注释以及它们如何与咖喱霍华德同构相关。

从属类型可以被认为是一个问题的答案:哪些类型对应于命题$ \ forall x \在S \ quad P(x)$中并且$ \在y \ T \ quad Q(y)中存在?

答案是,您创建了创建类型的新方法:依存积和依存和(coproduct)。从属产品表示“对于$ S类型的所有值$ x $,$都有$ P(x)类型的值。$”正常产品将是$ S = 2的从属产品,$两个值。从属产品可能会写为class Monoid c where e :: c (*) :: c -> c -> c idl :: (x::c) -> Eq x (e * x) idr :: (x::c) -> Eq x (x * e) assoc :: (x::c) -> (y::c) -> (z::c) -> Eq ((x * y) * z) (x * (y * z)) 。一个相关的和表示“某些类型为$ T $的值$ y $,与类型为$ Q(y)。$的值配对”,可以写成(x:T) -> P x

人们可以将它们视为从Set到一般类别的任意索引(联)产品的一般化,在其中可以明智地编写例如$ \ prod_ \ Lambda X(\ lambda),$,有时在类型理论中使用这种表示法。