One reason I haven’t been doing much blogging recently is that I’ve been spending a lot of time learning Haskell, a computer language with a number of intriguing features. Since I have previously remarked on weaknesses in Java’s type system, I thought I would start by remarking on Haskell’s type inference. Unlike many of the language’s other intriguing features, this one is easy to demonstrate and its benefits are easy to explain.
Consider this Haskell program:
main = do str <- getLine let n = read str putStr "Twice that is " putStrLn (show (n * 2.0))
Like C, C++, and Java, Haskell is statically typed: every variable has a type that is known at compile time. Unlike those other languages, though, you don’t have to explicitly declare the type of a variable when the compiler can figure it out. The compiler knows that
str is a string, because that’s what the standard library function
getLine returns1. The
read function is polymorphic and can translate a string into any of a wide variety of Haskell types, but the compiler can still figure out the type of
n, because it shows up later as an argument to
*; since 2.0 is a floating-point number, then
n must be one as well.
sethg@henbane:~/Desktop/hs$ ./a.out 3.5 Twice that is 7.0 sethg@henbane:~/Desktop/hs$ ./a.out 42 Twice that is 84.0 sethg@henbane:~/Desktop/hs$ ./a.out 0x10 Twice that is 32.0 sethg@henbane:~/Desktop/hs$ ./a.out fred Twice that is a.out: Prelude.read: no parse
I realize that programmers get into fervent religious wars over the question of static vs. dynamic typing, but I think I can avoid getting roasted by either side if I point out that if you have to use a statically typed language, it would be nice to use one with type inference. Why should we humans have to keep track of those tedious details if the computer can do it for us?
PS: Notice how in the code, the
read function appears before the call to print the phrase
Twice that is, but in the output of the running program, the error message from
read appears after that phrase. That’s lazy evaluation, another intriguing Haskell feature….
getLine is type
IO String. Explaining how the output of this function gets bound to a variable of type
String would require explaining Haskell’s monadic IO system, which I’m not ready to do just yet.