Monday 29 August 2016

Elm - Object-Oriented Brain and Types


I'm not embarrassed to admit that it took me a fair amount of time to get my head around object-oriented programming. For a long time I just couldn't figure out why it was a useful thing. That's probably got something to do with my background as a research scientist, and the type of problems I originally tackled during the first few weeks and months after I started learning to code.

After a while of staring at examples and messing about with classes in Python, it eventually clicked for me. A funny thing happened in between finally grasping the idea of objects and now… my brain has become object oriented.

There is a concept known as the law of the instrument, which was most famously expressed by Abraham Maslow as follows:

"I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail."

I now see most problems when I'm programming in terms of objects - "Oh I'll take that data and store it in this object, and it can interact with this, this and this though these methods, and it'll have these properties and some nice class methods and I'll chuck in this static method too". Now I don't think that this is inherently a bad thing, sure it can be taken to absurd extremes, but most of the time I think what I come up with is a decent solution that can be easily followed, modified, tested etc.

What happens if you're using a language that doesn't contain objects? I'm not taking about something like Rust where there's not objects, but there sort of are really, you can glue together structs and functions using the impl keyword and traits. Okay I'm probably over simplifying that, my Rust* isn't great but that's the way it seemed to me. In Elm there are no objects, but there are types…

Elm has strong, static typing. This means that all data in Elm has a type, and that type is used to dictate what you can do with that data. The compiler will tell you if you've used an Int in a function that expects a String. The compiler can tell from your source code, exactly how data flows through your program, and can tell how everything should connect together. If you pass the wrong type of data to a function, the compiler will tell you long before you run your code as it knows  what the type of the function is (more on this later) and the type of your data. This avoids many of the unexpected behaviours that arise when you're using languages that aren't statically typed, and particularly when you're working with a language like JavaScript or Python where you have duck typing.

What does static typing have to do with objects? Well in Elm you can define your own types, and these types represent complex data in the same way that objects can in OOP. Types in Elm can be defined using some simple tools: type annotations and type aliases.

If we use the Elm repl, we can see the types of values easily:


When you type an expression in the repl, the type of the evaluated expression is displayed immediately after (in the format "data : type". Most of this seems obvious, you have strings and their types are strings, or a number of type number or slightly more complicated you have lists which are of the types List "something", like List String or List Bool. You can even have lists of a generic type (see the empty list on line 16). There's something odd though…

Let's look at the type of a function, for example floor on line 19, it has a type of Float -> Int. This means that the type of the function is defined by the type of its input argument and the type that it returns. The type signature looks a lot like you define an anonymous function in Elm, using the syntax on line 25, and that's not a coincidence. I won't go into why this is here, but it's a pretty fundamental part of the language that I'll discuss in a later post.

As you can see in the example, Elm can infer the types of data a function will receive, but you can explicitly state them using type annotations using the same syntax as the type signature:


As you can see in line 12, you can't lie to the compiler, I checks the types even if you've annotated them. So that's all fine, but what if you want to pass more complex data to a function using records? Well you need to annotate the type of the record, and specify the types of all its component data. You can see this on lines 19 and 20. The record that's being passed into the function is relatively simple, what if you have lots of data in the record? Well no worries, let's just not annotate the type, and the compiler can infer the type. If you do that in the Elm repl you get the type signature on line 23. This shows that the function will take any generic type with that contains a ".name" field. This sucks! Everything should be more explicit, that'd make it easier to read. In the words of Raymond Hettinger "There must be a better way!", and of course there is. We can use type aliases to make this more readable, concise and maintainable. 


You can see the type aliases on line 5/6 and line 8. 5/6 shows a type alias of a Record with a name and an access field and 8 is an alias of a String. We then add a type annotation to the requestAccess function. This function takes a "Person" and a "Location" type, then returns a bool if they're allowed access. You can annotate any type, but you must remember that it doesn't do anything special, it merely is a form of shorthand for the annotations.

Type aliases are much lighter weight than objects in most languages, but I think that maybe they're a bit more transparent too. Pretty neat!

Update: There are also type unions, which as the name suggests groups types together, but I'll go into more depth about those in another post.

Note: Most of the examples here are based on the Elm docs regarding types, check them out here [LINK].

† - I love this article by Steve Yegge where he describes a terrifying world where there are only objects http://steve-yegge.blogspot.co.uk/2006/03/execution-in-kingdom-of-nouns.html
* - Rust is cool, I like it for the same main reason I like Elm; it has a clear domain except it's systems programming not web development. I might write some posts on it at some point.

Thursday 25 August 2016

Elm and Learning New Programming Languages

So like most people that have been coding for a while, I've got more and more interested in exploring new programming languages. It's kind of like visiting a foreign country, it's fun to experience other ways of life. Sometimes though you're disappointed when it's too similar to home other times it's a bit overwhelming if it's too different.

What you really want is something in the middle, so maybe you walk through a supermarket when you're abroad and you marvel at the unusual selection of canned goods, and then right in the corner you notice a can of baked beans. It always makes me smile, and then you think "What if they taste different!?", and you end up having beans for lunch, which is nice but you end up thinking that you should have been a bit more adventurous. Anyway, you can see what I'm getting at, it's nice to try something new, but sometimes a bit of familiarity doesn't go amiss.

I learned to code in Python, and while a lot of programming paradigms are captured by the language, it is mainly an imperative language, that is where you make statements to change the state of a program. For example maybe you want to count all the odd numbers in a list, you could do it in a hundred ways but here's one that is classically imperative:


One day I was reading about how to be a good programmer, and people kept mentioning that you should learn more than one language and you should try to make it pretty different from a language you know. One argument for that is that it show you other ways to program, and Haskell is often used as an example of this. So I started to learn a bit of Haskell, using http://learnyouahaskell.com/, and my mind started to melt! I wasn't aware that there was any other way to program apart from using imperative style code.

By this point, I had been exposed to many functional programming paradigms in Python, such as the idea of functions as first-class citizens, map, filter, list comprehensions… but it never occurred to me that programming languages existed that used these traits as the basis for the language and built upon them.

I learned a fair bit of Haskell, but in the I stopped learning it in the end because it was utterly mind-bending trying to think of an algorithm to solve a particular problem. Also, because it was so unfamiliar I couldn't think of anything that I could actually use Haskell for! To make this clear, this was because of my lack of understanding, nothing to do with Haskell itself. It wasn't an utter loss though, functional programming stuck with me, and I definitely started using it more in Python after learning a bit of Haskell.

Time passes and I'm messing around with JavaScript, in particular languages that compile to JavaScript (which is a super interesting topic I'll hopefully discuss in more detail in another article) like TypeScript, and I came across Elm, and it properly intrigued me. Elm is a purely functional programming language that compiles down to HTML, CSS and JavaScript and can be used to make front ends for websites and web applications. It feels a lot like Haskell in syntax.

The nice thing about Elm is that it has a really clear application, in an area I'm interested in at the moment, which makes it easier to learn for me as I have a goal to work towards. I've started learning a bit of Elm just using the main documentation, and it's already starting to cement a lot of the more nebulous aspects of functional programming (things like Currying). I suppose this is to be expected, but what I've been surprised about is that I feel like it's teaching me to be a better web developer too, which is really neat!

Elm is probably not going to replace things like React and Angular any time soon, if ever, and it's still in flux as a language so it probably not ready for "production" code, but for a hobbyist wanting to learn about good web development and FP it seems ideal. I feel like Elm is the programming language equivalent of baked beans in a foreign super-market, it feels new and different, but has familiar aspects (the web development parts!).

I'm going to write about Elm and the little web application that I'm developing using it in upcoming posts. Let me know what you think of Elm, Haskell and FP in the comments. Have you used Elm? What did you think? Has anyone learned to code using FP and then moved across to an imperative language?