In this blog post, We will be talking shortly about Haskell’s type system( which is a very broad topic, this post won’t eve scratch the surface). I will just explain what is needed to explain
partial function application means and how is it done in Haskell.
N.B. Installing Haskell is very easy with Stack, if you are on a Mac, you can just do
brew install haskell-stack to install Stack. Then starting the
repl is as easy as writing
stack ghci in your favorite terminal.
Haskell is a statically typed functional programming language. That means everything has a type associated with it and the compiler checks and enforce types at compile time. So there are two phases of code in Haskell one is
Type Level Code which involves type definition, type constructors etc. Another is
Term Level Code which is the body of the program. That doesn’t necessarily mean you will always have to write type signatures for trivial things. Haskell has a very powerful
Type Inference system which can infer types from untyped code, so you don’t have to specify types of all the things but Haskell will infer them from the code and complain if types of anything doesn’t match. It uses
Hindley-Milner Inference algorithm( well, an extended version of it for
What are types?
Types are how we group a set of values together that share something in common. Sometime that something is abstract and sometime that something is a specific model of a particular concept or domain. We can think of types as
Set from mathematics to better guide our intuition. So for example what is the type of number 2, well it’s a number, a member of the set of
Natural Numbers. Type of
a is character. You know this if you have worked with any statically typed programming language before like
C/C++ or Java. However Haskell takes it to a whole new level.
How do we define types for a simple addition function?
Let’s write the function signature first then we will explain it.
1 2 3 4
What we are telling the Compiler by this is we have an
add function which takes two
integer and returns result by adding them. If you we remember what I was telling about currying in my previous post you can’t accept two params into a single function. You have to define them a nested lambdas, but it’s a syntactic sugar Haskell provides to make it more useful, still make the core conform to whatever lambda calculus provides.
So the above function is pretty straight forward. Lets get to the point and talk about the main focus of this blog post.
Partial function application
Partial application is the notion of supplying less arguments than the function expects. Let’s see an example, we defined an
add function in previous section, now if we want to define an
increment function in terms of it we can do something like
ahh that seems simple, now lets explain how that works. We are assigning value of
add 1 as the body of our
We know from the type signature of
add that it takes two integer and return their sum. So what happens when we supply it only one argument. We the value
1 gets bound to the first param
x in the definition of
add function and we get something like
1 2 3
Which is another function. A partially applied one. If we want to see it from the point of Lambda Calculus it will be more clear
1 2 3 4 5 6 7 8
Thats what is happening with our
add function too because haskell is typed lambda calculus. So
add 1 is an partially applied function waiting for another application to a value. It’s easy but a very powerful idea, and lets one write cool functions in terms of other simpler functions. Composability for the win!.
We can similarly write these functions too,
1 2 3 4 5 6 7 8 9 10 11 12 13
The examples in this blog post were intentionally contrived but The idea of
partial function application is a profound one and we can do all sort of cool things with it.
Thats all for today. Hope you enjoyed it.