Idris 语言教程有简单易懂的依赖类型概念示例: http ://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#first-class-types
这是代码:
isSingleton : Bool -> Type
isSingleton True = Int
isSingleton False = List Int
mkSingle : (x : Bool) -> isSingleton x
mkSingle True = 0
mkSingle False = []
sum : (single : Bool) -> isSingleton single -> Int
sum True x = x
sum False [] = 0
sum False (x :: xs) = x + sum False xs
我决定在这个例子上花更多的时间。在函数中困扰我的sum
是我需要显式地将single : Bool
值传递给函数。我不想这样做,我希望编译器猜测这个布尔值应该是什么。因此,我只传递Int
或传递List Int
给sum
函数,布尔值和参数类型之间应该存在一对一的对应关系(如果我传递一些其他类型,则不能进行类型检查)。
当然,我理解,这在一般情况下是不可能的。此类编译器技巧要求我的函数isSingleton
(或任何其他类似函数)是单射的。但是对于这种情况,在我看来应该是可能的......
所以我从下一个实现开始:我只是single
隐含了参数。
sum : {single : Bool} -> isSingleton single -> Int
sum {single = True} x = x
sum {single = False} [] = 0
sum {single = False} (x :: xs) = x + sum' {single = False} xs
好吧,它并没有真正解决我的问题,因为我仍然需要以下面的方式调用这个函数:
sum {single=True} 1
但我在教程中阅读了关于auto
关键字的内容。虽然我不太明白是什么auto
(因为我没有找到它的描述),但我决定再修补一下我的功能:
sum' : {auto single : Bool} -> isSingleton single -> Int
sum' {single = True} x = x
sum' {single = False} [] = 0
sum' {single = False} (x :: xs) = x + sum' {single = False} xs
它适用于列表!
*DepFun> :t sum'
sum' : {auto single : Bool} -> isSingleton single -> Int
*DepFun> sum' [1,2,3]
6 : Int
但不适用于单一值:(
*DepFun> sum' 3
When checking an application of function Main.sum':
List Int is not a numeric type
有人可以解释一下目前在这种单射函数用法中是否真的可以实现我的目标?我观看了这个关于证明某些东西是单射的短视频: https ://www.youtube.com/watch?v=7Ml8u7DFgAk
但我不明白如何在我的例子中使用这样的证明。如果这是不可能的,那么编写此类函数的最佳方法是什么?