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

From C++ to Haskell

If you had been in OOPs for as long as you can remember, jumping into functional programming (FP) can be tiring and if you had chosen haskell, at times it would be disappointing. After a while with Haskell, you will never want to go anywhere else and you will feel sick with all other languages!. I spent 5 years with enterprise scale C++ code base then jumped into Haskell. I mentioned ‘enterprise’ OOPs, means, it is either legacy code or a huge codebase with leaky abstractions everywhere.

My learning curve could be summarized as follows:

  1. Unlearn traditional encapsulation, class members etc., from OOPs; Learn to appreciate concise code and small variable scopes in FP
  2. Work with types, function signatures, type classes etc., rather than classes
  3. Pattern matching and equational reasoning.. a humble assignment operator from OOPs has a completely different meaning in Haskell!
  4. Most stuff can be solved by recursing and accumulating.. infact, a recursive code is more easy to write and read when compared to iterative code.
  5. Abstract away iterations and conditional reasoning as much as possible, solve things by function composition and currying
  6. ‘Functions as first class citizens’ helps to find neat way to do things. Importantly, arranging function parameters to support better currying is super fun
  7. Lazy evaluations.. I hit this wall very hard only after I started working with disk IO.
  8. Type errors and ‘could not deduce’ errors. There were times, when I wrote only couple of lines of code, but ended up fixing type errors all day. There are also days when I would expect a particular type error, but instead spend time to fix all the other unexpected type errors. All said, it always feels good to fix compilation errors rather than firing up GDB on a C++ core dump! a SEGV fault in Haskell application is very very rare.
  9. Everything works in first shot! and no core dump! .. almost always this will happen and many a times, you would never think about writing unit tests. Compilation itself is a very important happy path unit test 🙂
  10. My code is getting cleaner as I learn more of Haskell! .. this will keep on happening. No matter how much ever you discover, there are always more ways to abstract things. Since code refactoring is very cheap, you will never think twice to refactor that age old code and make it more concise.
  11. Coming across weird blog posts, papers, talks by Haskell theory gurus.. This one should not scare you. With time, you will know what to look for and what all to skip to get your work done fast. It is fun to solve real world problems by stealing ideas and implementations done by these gurus.

Did I mention, I am not very interested in Math? People always feel, you should be a Math guru to use advanced haskell features. Yes, being a Math guru helps you pick up things quite easily. But you can survive and do better in Haskell even with lesser interest in Math

Now I am dirtying my hands with Erlang; with each passing day I feel terrible to miss the wonderful static type system of Haskell.

Coding as an employee

You are / about to be, an employee of this software company and coding is part of your job. Now, how would it feel like? What sort of stuff would your employer expect? What stuff would you expect?

The right question to ask is this: What is the quality of code you can deliver and how complex are the problems you can solve? Most of the problems out there that needs paid employees to keep the business running can be broadly classified as follows.

Case 1 – New product in the market space; does not have much end users; small independent self contained team:

  • This is the fun part in your career you would ever find.
  • You get to write a lot of code, implement features day in and day out.
  • You can take some liberty and refactor code the way you see fit
  • See how the company manages to expand its business and how the product evolves
  • Free knowledge all around the company which would come in handy if you start your own company someday

But,

  • Be prepared, the feature that you worked hard on might go to trash very soon. The product would evolve so rapidly that you might have to scrap your code way too often before it reaches the end user.
  • The work might get so interesting that you would forget to balance it with your life

Case 2 – A fairly proven product; already has too many components working together solving a variety of problems; user base is increasing rapidly than the product can handle; the company has found some huge investment and are trying make the product go wild:

  • You get to read and analyse a lot of code, and write few lines here and there.
  • Writing clean code is mandatory. In some cases if you are lucky, you get to refactor the old ‘bad’ codes and leave things cleaner than it was earlier.

Case 3 – Coding for an enterprise:

  • You get free knowledge from the seasoned seniors,  you can get to know how their career has shaped up.
  • You have this product which makes a lot of money and has a lot of users.
  • You get to read huge code base and write very little. Sometimes, even if you see bad code, you are not supposed to change it as it would be too ‘costly’ for the company to change code unless and until it is really needed. (Chances are, the company never took risks in migrating to newer, cooler technology stacks; never tried Haskell. Haskellers never have to be afraid of refactoring code!)

Irrespective of what you are, when you code as an employee, the following points helps in finding that inner peace:

  • Always keep a look out, explore the latest developments in the tools you use, and explore new areas.
  • Keep experimenting with what you have learned. Even if the company does not need it, make it for your satisfaction and give it out for free.
  • Keep the business owner mindset alive!

Build a career

People work for a number of reasons and experience a variety of things while at work. How many people have you met who gets to do 100% of what they like at work and be 100% content in their life all at the same time? Must be very few. Finding such an infinite loop of happiness is very hard. But you can very well find a circle of balanced work and life. The only way to find this balance is to save as much of your energy as possible while at work and spend it afterwards. Exhausting yourself at work cannot make your life any better.

How to save your energy? One sure-shot way is by being good at the tasks you do. May be you are only 60% happy doing it, but 60% is good enough. You are not too tired afterwards any ways! May be the lack of 40% happiness makes you frustrated and lose more energy? Read on.

How to get good at the tasks you do and feel happy about it? Well, I got inspiration to write this post after listening to this: Building your career. You try it too, you might get the answer.

So, start building your career now and balance it with your life. Sounds hard, but gets easy when you start trying.