在Idris中,为什么接口参数必须是类型或数据构造函数?

时间:2018-05-26 20:10:28

标签: math types interface idris type-theory

为了与Idris进行一些练习,我一直试图将各种基本的代数结构表示为接口。我最初组织事物的方式是让给定接口的参数设置为上面的各种操作,方法/字段是各种公理的证明。例如,我正在考虑定义Group,如此:

Group (G : Type) (op : G -> G -> G) (e : G) (inv : G -> G) where
  assoc : {x,y,z : G} -> (x `op` y) `op z = x `op` (y `op` z)
  id_l  : {x : G} -> x `op` e = x
  id_r  : {x : G} -> x `op` e = x
  inv_l : {x : G} -> x `op` (inv x) = e
  inv_r : {x : G} -> (inv x) `op` x = e

我采用这种方式而不仅仅是制作opeinv方法的理由是,在同一组中讨论相同的组是更容易的方法。就像在数学上一样,谈论集合是一个群体是没有意义的;只讨论一个指定操作是一个组的集合才有意义。通过不同地定义操作,相同的组可以对应于两个完全不同的组。另一方面,各种界面法则的证明不会影响群体。虽然法律的居民(证明)可能不同,但它不会导致不同的群体。因此,对于声明多个实现没有用处。

更基本的是,这种方法似乎更好地代表了数学概念。将一个集合作为一个组来讨论这是一个类别错误,所以我的数学家并没有因为使用group操作成为一个接口方法而对断言这一点感到兴奋。

然而,这种方案是不可能的。当我尝试时,它实际上做了类型检查,但是一旦我尝试定义一个实例,它就不会:idris抱怨说,例如:

(+) cannot be a parameter of Algebra.Group
(Implementation arguments must be type or data constructors)

我的问题是:为什么这个限制?我认为这是一个很好的理由,但对于我的生活,我看不到它。就像,我认为Idris崩溃了价值/类型/种类层次结构,因此类型和价值之间没有真正的区别,那么为什么实施特别对待类型呢?为什么数据构造器是专门处理的?这对我来说似乎是随意的。

现在,我可以使用命名实现来实现相同的功能,我想我现在最终会这样做。我想我只是习惯了Haskell,你只能为给定的数据类型提供一个类型类的实例。但它仍然感觉相当随意....特别是,我希望能够将例如半环定义为元组(R,+,*,0,1),其中(R,+,0)是一个幺半群而(R,*,1)是一个幺半群(加上ditributivity法则)。但是,如果没有上述方案,即使使用命名实现,我也不认为我能够轻松地做到这一点。我只能说R是否是幺半群 - 但对于半环来说,它需要以两种截然不同的方式成为幺半群!我确信有一些样板式类型的同义词或类似的东西(我可能最终会这样做),但我真的不明白为什么这是必要的。

$ idris --version
1.2.0

0 个答案:

没有答案