I was working on a website scraper the other day and decided to write it in Haskell to re-familiarize myself with the language, and to learn about the http and html-related libraries available for Haskell. I have some things to work out with my code (right now, it hangs when loading the URL), but through this project I was reminded of some of the things that went through my head when I last used Haskell 6 years ago.
My favorite thing about Haskell is the idea of being completely clear and explicit about the type of data you're passing throughout the program. To give an example about what I'm talking about, here's a function that takes a list of characters and returns the first one:
first :: [Char] -> Char first s = s !! 0
This function only ever accepts a list of Chars, and will only
ever return a Char. Without including the first line of this
function, the compiler infers a more general type for this
[a] -> a. This function type uses the
a to say it takes a list of something,
and returns a single instance of that same something.
In 2010, I stopped programming in Haskell and learned Ruby
on Rails because that was the easiest way to get a job.
So the Haskell community is small and not focused on web
development. But there's a few other things that keep me
from programming in Haskell on a regular basis. Its
strict type system is both good and bad. Going back to
my web scraper, here's a ghci session that displays the
type of a Haskell library's
which takes a url and returns an HTML document. The
:: operator can be read as "is of the type".
$ ghci Prelude> import Text.HandsomeSoup Prelude Text.HandsomeSoup> :t fromUrl fromUrl :: String -> Text.XML.HXT.Arrow.XmlState.TypeDefs.IOSArrow b (Data.Tree.NTree.TypeDefs.NTree Text.XML.HXT.DOM.TypeDefs.XNode)
We see this function takes a String and returns something
else. The string part makes sense - a string is how anyone would
represent a URL. But what about the crazy return type? Why isn't
this function type something simple like
String -> XmlDocument?
That's the secret of Haskell. When you think about it, the
fromUrl function needs to do some I/O work,
changing the state of the system in this process.
Invoking side effects (i.e. doing I/O work) goes against
the ideas that Haskell is based on. In fact, in Haskell
terms you'll hear of code that has side effects described
with the derogatory word "impure".
Haskell has dealt with this (making the impure code pure again)
through some complicated math, ultimately
coming up with the "Monad" type.
For details on input/output in Haskell, see:
In college I was lucky to have professors
teach me about functional programming, specifically in Haskell.
So I learned about monads, and I've heard that an
Arrow is a type of
monad. But I still can't really wrap my head around it.
So that's as far as I can get off the top of my head into
understanding the return type of
And whether you really understand this return type or not, you have to admit that it's still not obvious. By writing code that passes around complicated types, you create a complex program that takes up a lot of mental space.
So, that's been my take on Haskell in my years of not using it. There's lots of good things to learn by writing code in a functional language. I assume that we can find useful ideas in other programming paradigms as well, such as logic programming in Prolog. That's more difficult, though. In my experience Prolog is way more different from imperative programming than Haskell.
We can also keep in mind that computers are procedural underneath it all, at the machine code level. In addition, think about the amazing complexity that the Linux kernel developers are able to manage through procedural C code. So in the future we may see functional or some other kind of programming become the norm, as programming languages themselves were invented as an abstraction of machine code. But who knows. We do think procedurally, and it's just second nature for instructions of a routine to come one after another, in contrast to the mathematical style of a function as a definition from one domain to another.