Type-directed search with dependent types

Ben Sherman

August 12, 2014

Types have the potential to be, all at once, specifications, documentation, and proofs of correctness. Because Haskell's got a powerful type system, Hoogle, a tool for finding terms by approximate type signature, proves rather valuable. But in a dependently typed language, types reach their pinnacle. The combined variety and precision of types in such languages means that type-directed search is a really enticing proposition.

So I decided to create such a type-directed search! I wrote the :search function for Idris, a dependently typed programming language inspired by Haskell. I took an approach guided by type isomorphism (which is somewhat different from Hoogle): when :search matches two types, one can be constructed from the other.

This is a talk which I gave at the Haskell DC meetup in Washington, D.C on August 12, 2014.


In the first part of the talk, I discuss how programming languages vary in terms of what can be ascertained statically about their programs, particularly in regards to type systems. When type systems are powerful, as they are in Idris, I prefer type-driven development to test-driven development. I demonstrate that the property map f . map g = map (f . g) is false for ML but prove its veracity for Haskell by hand.

In the second part of the talk, I construct a term in Idris which bears witness to the fact that map f . map g = map (f . g) is true in Idris. I demonstrate the :search feature in Idris and explain how it works. I also discuss some strategies I employed and issues I faced when developing :search, and ways in which :search can be improved in the future.

 1 eqList : {a : Type} -> {x, y : a} -> {xs, ys : List a}
 2   -> x = y -> xs = ys -> x :: xs = y :: ys
 3 eqList {x} {y} {xs} {ys} p q = replace {P=\ts => x :: xs = y :: ts} q
 4   (replace {P=\t => x :: xs = t :: xs} p (refl {x :: xs}))
 5 
 6 
 7 
 8 
 9 mapFusion : {a, b, c : Type}
10   -> (f : a -> b) -> (g : b -> c) -> (xs : List a)
11   -> map (g . f) xs = map g (map f xs)
12 mapFusion f g [] = refl
13 mapFusion f g (x :: xs) = eqList refl (mapFusion f g xs)
14 

View slides in full (PDF).