Type Inference

Statically typed programming languages would compile only if you specify types of the things that you have in your code. In functional programming world, you tend to have plenty of functions in various scopes abstracting away bits and pieces of logic. I strongly believe, the future is mostly functional and rarely object oriented for this very reason. After this, comes other reasons which I would save for a separate post.

Now that you have abstracted logic, you do get lazy to write the types of things. Type inference to the rescue! Quick definition from haskell wiki:

Type inference is a feature of the type system which means that concrete types are deduced by the type system where ever it is obvious. If you add an integer variable x to a numeric literal 2, then the type system concludes that 2, which in principle can represent 2 for every number type, must also be an integer, since + supports only addition of numbers of the same type.

Try this out in your ghci:

 Prelude> data Apple = Apple Int deriving (Show)
 Prelude> data Orange = Orange Int deriving (Show)
 Prelude> let (Apple a) ^+ (Apple b) = Apple (a + b)
 Prelude> let addTwice x y = (x ^+ y) ^+ (x ^+ y)
 Prelude> addTwice (Apple 1) (Apple 1)
 Apple 4

 

How did it work? Well, the type of the expression ‘addTwice’ got inferred by the haskell compiler:

 Prelude> :t addTwice
 addTwice :: Apple -> Apple -> Apple

 

Go ahead, experiment this one:

Prelude> addTwice (Apple 1) (Orange 1)

 

Boom!

<interactive>:47:21:
 Couldn't match expected type Apple with actual type Orange
 In the second argument of addTwice, namely (Orange 1)
 In the expression: addTwice (Apple 1) (Orange 1)
 Prelude>

Beautiful the error message!. You can use this as a weapon to write neat code, and make it neater by refactoring at any time, without worrying too much about introducing accidents in your code.

I had been basking on Haskell’s type inference all this while. When I was experimenting on scala as part of my course, I was pretty surprised, scala’s compiler was complaining for this statement:

f.chars.foldLeft(List())(makeBits)

I had all the types set, the return type of the function, the inputs and outputs of makeBits, everything; still the compiler failed to accept my code:

 [error] found : List[(Char, List[patmat.Huffman.Bit])]
 [error] (which expands to) List[(Char, List[Int])]
 [error] required: List[Nothing]
 [error] f.chars.foldLeft(List())(makeBits)
 [error] ^
 [error] one error found
 [error] (assignment/compile:compile) Compilation failed

 

This fixed the problem:

f.chars.foldLeft(List():List[(Char,List[Bit])])(makeBits)

 

Had it been haskell, I would have used ‘[]’ for the accumulator. It would have just worked. Another reason for me to vote for haskell!

Advertisements