Idris language tutorial has simple and understandable example of the idea of Dependent Types: http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#first-class-types
Here is the code:
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
I decided to spend more time on this example. What bothers me in sum
function is that I need to explicitly pass single : Bool
value to function. I don't want to do this and I want compiler to guess what this boolean value should be. Hence I pass only Int
or List Int
to sum
function there should be 1-to-1 correspondence between boolean value and type of argument (if I pass some other type this just mustn't type check).
Of course, I understand, this is not possible in general case. Such compiler tricks require my function isSingleton
(or any other similar function) be injective. But for this case it should be possible as it seems to me...
So I started with next implementation: I just made single
argument implicit.
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
Well, it doesn't really solve my problem because I still need to call this function in the next way:
sum {single=True} 1
But I read in tutorial about auto
keyword. Though I don't quite understand what auto
does (because I didn't find description of it) I decided to patch my function just a little bit more:
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
And it works for lists!
*DepFun> :t sum'
sum' : {auto single : Bool} -> isSingleton single -> Int
*DepFun> sum' [1,2,3]
6 : Int
But doesn't work for single value :(
*DepFun> sum' 3
When checking an application of function Main.sum':
List Int is not a numeric type
Can someone explain is it actually possible to achieve my goal in such injective function usages currently? I watched this short video about proving something is injective: https://www.youtube.com/watch?v=7Ml8u7DFgAk
But I don't understand how I can use such proofs in my example. If this is not possible what is the best way to write such functions?
False
). Redefine the functions, swappingTrue
andFalse
, and you'll see thatsum' 3
works, butsum' [1,2,3]
doesn't. – Anton Trunov