Dependent Types: Level up Your Types

Dependent Types: Level up Your Types

Dependent Types: Level Up Your Types Marco Syfrig University of Applied Sciences Rapperswil Supervised by Prof. Peter Sommerlad Seminar—FT2016 “It typechecks! Ship it!” first in Listing 1 that returns the first element – Edwin Brady, designer of Idris [Bra] of a vector. Dependent types make types into first-class lan- 1 public static Integer guage constructs and ensure type safety depending first(Vector<Integer> vec) { on values and not only types. They help to get rid 2 if(!vec.isEmpty()) { of all unit tests because dependent types require a 3 return vec.get(0); proof that a function behaves as expected. This proof 4 } needs to be written by the developer himself and ver- 5 return null; ifies that the function works correctly for all possi- 6 } ble inputs. So a type, in the end, is a proof for the compiler and no unit tests are needed. Type check- Listing 1. A check for the existence of an element is needed in a ing may become undecidable since these types can non-dependently typed language like Java depend on any value or expression. This paper gives an overview what problem de- The check for null is omitted for read- pendent types solve, kinding, dependent type theory ability. One crucial thing for the correct- and then a fairly big part about the differences to ness is the check on line 2 that the vector other systems. It then shows some current ongoing vec is not empty. Otherwise, a call like research and finally explains why dependent types first(new Vector<Integer>()); results in may play a bigger role in the far future. a run-time error and in the case of Java throws an ArrayIndexOutOfBoundsException. No- tice also that the non-emptiness check has to be 1 Introduction done at run-time which takes a little bit of time The initial quote “It typechecks! Ship it!” from every time the method is called. The last burden is Edwin Brady [Bra]—designer of the dependently on the caller that has to check if the result is null typed language Idris—may be exaggerating, but it and if so handle it. Another implementation could highlights one of the main reasons of type check- also throw and catch the above-mentioned excep- ing. A developer wants to rule out as many errors tion or the caller could check for non-emptiness as possible by automatically type checking his pro- before calling. However, there is always at least gram. This is where dependent types come into one run-time check required and it has to be spec- play. They help a developer find even more errors ified and clear whether the caller or callee does during compile-time rather than only at run-time this check. Here is where dependent types step in with run-time checks. Consider the Java method and resolve this issue. 1 With a dependent type of vectors we can en- Listing 3. It computes a type that depends on the code the requirement for non-emptiness into the passed value. This can then be used in another type. function sum that calculates the sum of a single value or a list, depending on the passed type. first :Πn : Nat:Vector(n + 1) ! Int (1) 1 isSingleton : Bool -> Type 2 isSingleton True = Nat 3 isSingleton False = List Nat The preceding lambda expression (1) is taken 4 from [Pie04] and explained in Section 3 in greater 5 sum : (single : Bool) -> isSingleton single -> Nat detail. It represents a function signature for a 6 sum True x = x function that also returns the first element but 7 sum False [] = 0 with a dependent type. Passing an empty vec- 8 sum False (x :: xs) = x + sum False xs tor to first results in a compile-time error. List- ing 2 shows an implementation in the depen- Listing 3. Function isSingleton in Idris that computes a type dently typed programming language Idris [idr]. and returns it. The returned type is then used in sum . The realization is exactly the same; just the type The compiler checks for every possible input— is named Vect in Idris. which is really easy for just True and False—if a type is returned. 1 import Data.Vect Type systems should help build safer pro- 2 grams, have more expressive APIs, help a devel- 3 -- Natural numbers definition oper with hints and also the other direction, that 4 -- for better understanding type information should help the compiler to be 5 data Nat = Z | Suc Nat --zero | successor 6 more efficient. The following parts of the paper 7 first : Vect (Suc len) elem -> elem introduce a more formal definition of dependent 8 first (x::xs) = x types, explain the necessary knowledge to under- 9 stand the expression in l-Expression (1) and then 10 firstNat : Nat 11 firstNat = first Vect 0 Nat some parts of Idris to better understand code ex- amples as the ones shown above. Further, de- Listing 2. Typesafe function first to get the first element of a pendent types are compared to the more auto- non-empty Vect in Idris mated but less expressive refinement types and to C++ template programming which can achieve A Vect is created with the length and type the same but has different goals. It will be ex- it holds and Vect 0 Nat yields actually a dif- plained that it is expected that dependent types ferent type than Vect 1 Nat since the length will play a bigger role in the future as there is a is different. first expects a vector that has lot of research and development currently, espe- been created with the Suc Nat data constructor cially for Haskell. However, they will not play a which means it is bigger than 0. The compiler more important role in everyday programming as checks the correctness of the code by looking at long as such a type system cannot be merged with the function signature and the specified types an existing one that does not require a developer there. If they do not match, for example for to write his own proofs for every small property. the application first Vect 0 Nat on line The last section sums this up again. 11, the compiler throws an error about a type mismatch: (input):1:7:When checking an application of function first: Type 2 Kinds mismatch between 0 and Suc len. Types become first-class citizens in a depen- Another example of what can be done with dent type system. However, we can start writing dependent types is the function isSingleton in meaningless type expressions with the introduc- 2 tion of types as first class citizens and the abstrac- this expression. A kind is the type of a type con- tion and application rules for them. This section structor and in this case we state that Vector maps explains how this can be prevented with some- k : Nat to a type [Pie04]. This is the crucial part: thing called kinds. Just as we use the arrow type Vector is a type family and a parameter k : Nat can ! for functions to denote the arity, we use kinds be applied to it to yield a type. Normal types and to denote the arity of a type. Nat ! Nat has a dif- functions have a single definition. Type families, ferent arity than Nat ! Nat ! Nat. We need that on the other hand, have an interface that declares also for types. Readers not familiar with type sys- its kind and arity. We can now start building de- tems and their formal notation are advised to gain pendent types with this knowledge. The next sec- a quick overview by first reading [Syf15, Chapter tion explains dependent types formally so we can 2 Definitions]. then build practical examples in Idris in the sec- The rules are not relevant for the understand- tion after. ing, but they can be found in [Pie02, Figure 29- 1]. (Bool Nat) is a legal expression following these rules but meaningless. Applying Nat to 3 Dependent Types Bool should not be possible. We achieve this by As said before, types become first class citi- defining a system of kinds that restrict such ex- zens in a dependent type system. Readers famil- pressions which will now be explained. iar with functional languages, where functions This system should classify type expressions are first-class citizens, can draw the similarities. by their arity so a proper type cannot be applied Types can be used everywhere other expressions to a proper type anymore. The following listing is can be used: a function can compute and return taken from [Pie02, Chapter 29] and shortened for a type, types can be passed to a function, they simplification. can be computed, manipulated and assigned to a variable. An important distinction is, that int is a ∗ Kind of proper types that take no arguments for type and for example 1 is a value of type int. Non- instantiations like Bool and Bool ! Bool dependently typed languages can already pass 1 ∗ ) ∗ Kind of type operators. They are one arity as an argument and return it but not int itself. The higher. This means unary type constructors conclusion for the compiler is that it does not mat- for constructing a list of a proper type for ex- ter if 0 or 1 is passed since they are both of type ample. int and are equal at the level of types [Xi10]. They ∗ ) (∗ ) ∗) Kind of functions from proper types are interchangeable as far as type checking is con- to type operators. For example, binary type cerned.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    12 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us