33

I'm studying Haskell for the purpose of understanding functional programming, with the expectation that I'll apply the insight that I gain in other languages (Groovy, Python, JavaScript mainly.)

I choose Haskell because I had the impression that it is very purely functional, and wouldn't allow for any reliance on state.

I did not choose to learn Haskell because I was interested in navigating an extremely rigid type system.

My question is this: Is a strong type system a necessary by-product of an extremely pure functional language, or is this an unrelated design choice particular to Haskell?

8
  • 6
    If you don't want to explicitly type anything, you don't need to explicitly type anything. Haskell can infer types just fine on its own. And it's not like you're going to have a single variable potentially storing two incompatible types.
    – Anon.
    Dec 22, 2010 at 3:45
  • 4
    @Anon yes, but your lists must be homogeneous. Trust me, this sort of thing can get in the way, even with type inference. Dec 22, 2010 at 11:34
  • 13
    @FarmBoy and what is wrong with the use of Maybe? Java really makes you use Maybe on all classes, which is the weird thing to do. Apr 20, 2011 at 22:06
  • 3
    And if you really want to use a heterogeneous list you can of course use algebraic data types. Apr 20, 2011 at 22:14
  • 1
    @mathepic at this point we have really lost track of my original question, which was a perfectly valid question. Apr 20, 2011 at 22:36

7 Answers 7

40

I believe that understanding Haskell's type system is an amplifier to understanding functional programming.

The thing about purely functional programming is that in the absence of side-effects, which allow you to do all sorts of things implicitly, purely functional programming makes the structure of your programs much more explicit.

Haskell prevents you from shoving things under the carpet, forces you to deal with the structure of your program explicitly, and it teaches you a language to describe these structures: the language of types. Understanding types, particularly rich types as is Haskell, will make you a better programmer in any language.

If Haskell wasn't strongly typed, concepts like monads, applicative functors and the like would never have been applied to programming.

3
  • 2
    This is a good answer, my addition is that while the type system may seem unusual at first, later on when you start learning the more advanced concepts you will see that there are certain things that can only be done because of the adherence to that type system (add STM and Data Parallel to the list above). Things that would be non-starters in other type systems fit naturally with the Haskell system. My advice: stick with it for awhile, let it sink in over time (it's not a "cram" language).
    – anon
    Dec 7, 2011 at 3:05
  • 2
    I know that this is a super old answer, but I actually disagree. I think that, as explicit as some things may be in the language, the type system, especially with monads such as State and Parsec, sweeps a TON of stuff under the carpet. This is actually very greatly interfering with my ability to learn the libraries of the language. Jan 7, 2013 at 15:26
  • 4
    @SavanniD'Gerinel: I think in this answer "shoving things under the carpet" does not mean adding implicit functionality (which Haskell does in a controlled way e.g. through monads, and which helps to reduce boilerplate) but rather do allow some piece of code do something it is not expected to do. E.g.: a pure function in Haskell will never have side-effects. Period. In many other languages you can promise this in a function's documentation, but nothing in your language will prevent you from shoving in some side-effects somewhere in your code.
    – Giorgio
    Feb 23, 2014 at 8:49
33

The most dynamically typed functional language is arguably Scheme. That said, Haskell's type system is an indicator of its purity. It's a question of "how does one measure purity?". Haskell's type system lets you easily cordon off impure actions in IO. To do that, you need a static type system.

But let's say Haskell's type system has nothing to do with functional programming. It would still be the height of hubris to claim that the type system wouldn't help you in this educational endeavor. Haskell's type system is rich and complex, and all the more interesting when compared to the type systems of C++ and OCaml.

Is it an obstacle? No, I think it is an asset. Try to consider how to deal with Haskell's laziness without IO for example.

4
  • 8
    +1 Haskell's type system can be your friend once you get used to it. Dec 22, 2010 at 13:24
  • "To do that, you need a static type system". Really?
    – J D
    Feb 25, 2012 at 19:51
  • 1
    "all the more interesting when compared to the type systems of C++ and OCaml". Have you studied OCaml's first-class higher-order modules and structurally typed inferred object system and polymorphic variants?
    – J D
    Feb 25, 2012 at 19:53
  • 2
    @JonHarrop or an effect system or some way of measuring/evaluating purity. Yep, that's why it's interesting to compare them. Different choices make for different languages. Feb 25, 2012 at 20:23
20

Clojure is dynamically-typed, and almost as pure as Haskell, so there's a good argument that the Haskell's type system was more of a design choice than an absolute requirement. Both definitely have their strong points, so you may want to consider Clojure if you really don't like Haskell's rigidity (but see below).

When I first started using Haskell, I considered the type system to be annoying, and only tolerated it because of type inference. I soon discovered that many of the type errors the compiler complained about things that wouldn't have worked anyway even if the compiler had let me do them (e.g. accidentally using map instead of concatMap). I then discovered that programs that passed the type check were usually correct, or at least close to correct. I even had a lazy phase where I did refactoring by changing a function type and letting the compiler tell me what else needed to be changed. Finally, I realized that Haskell's type system was actually very expressive and started designing my programs around types. That is the Holy Grail of Haskell.

2
  • Another thing to note: I learned functional programming using both Scheme and Haskell at about the same time (the former for a class and the latter for fun). I found that understanding recursion was much easier with Haskell's pattern-matching than with ifs and conds in Scheme, which I imagine also carries over to Clojure. Dec 6, 2011 at 22:10
  • @Larry Coleman: +1 for describing precisely my own experience with types systems: first C++, then Ocaml, and now my own language Felix. Yes, I still refactor by chasing down compiler errors.
    – Yttrill
    Jan 7, 2012 at 1:36
8

Haskell's type system is key to its ability to isolate effects from pure code. Unless you can isolate effects in another way or you remove effects entirely, a strong static type system is a requirement for pure functional programming.

Haskell is a very good example of a language with a strong, static type system. If you want a broad and rounded education in computer science and programming language design in particular, Haskell would be an excellent choice as one of the languages that you should learn.

The type system shouldn't be a huge obstacle. People who program tend to, even when using dynamic languages, follow typing conventions that can be encoded using Haskell's type system. Haskell also features type inference which alleviates verbosity when compared to languages like C++ and Java. When you get an error message, the compiler is only telling you at compile time what a language with dynamic types would tell you at runtime.

The opposite of a dynamic type system is a static type system, not a strong type system. A strong type system is the opposite of a weak type system.

1
  • 1
    For example, C is statically but weakly typed. You have types, but it's easy to subvert the typesystem completely, play around with the underlying machine-specific representations etc. Many dynamically typed languages OTOH are quite strongly typed - few implicit casts, few ways (if any) to subvert the type system.
    – user8709
    Jun 19, 2011 at 2:32
4

It tells you right away when you make dumb mistakes. This is helpful. I have been working in Racket (Scheme) this last term, and there have been a number of times where I have passed an unparsed s-exp where I expected a parsed ast to some function in my interpreter, and it only showed up in my medium sized test suite. If I had some static typing, it would have been an brought to my attention right away.

Of course, logic errors can't really be caught by the type system, but the number of ways in which you can screw up is greatly diminished.

As well, type inference lets you ignore the type system if you wish. It's still there, but it doesn't require active input on your part. It's still helpful to understand the types of your functions, but correct code will work fine.

Haskell's purity is encoded in its type system. The IO monad is a type level construct that stops impure code from leaking into pure functions, so the purity is guaranteed by the type system.

4
  • 8
    If you think you can ignore Haskell's type system, then I think you haven't coded much Haskell. Dec 22, 2010 at 11:33
  • Not ignore so much as ignore it as much as type out the function, load it in GHCi, and go :t on it. But you are still going to need to sprinkle in some fromIntegral or other functions in sometimes. Dec 22, 2010 at 14:41
  • 1
    Tyr, even with type inference, 90% of using and coding Haskell functions is getting the damned things to mesh with each other, which requires an understanding of its type system and arcane typechecking error messages. Even ":t" is not a magical solution, just the first step to understanding how to make the program compile.
    – Andres F.
    Nov 13, 2011 at 21:28
  • Well, some parts are messy, I agree. I really think that the numeric stuff in the prelude could stand to be cleaned up and fixed, because as it stands, it's a terrible mess. But most of the key functional aspects are pretty clean. map, filter, foldr/l, and other fun functional functions work quite nicely. Nov 15, 2011 at 2:05
2

Being a "functional" language, means (apart from other things) that functions are first class objects in the language.

Being a "pure" language means that functions are mathematical functions (as opposed to procedures) -- given the same input, they always produce the same output.

A "pure functional language" is one where both the above hold. I am not aware of a "pure-ly functional language".

A strong type system is one clean way of having a pure yet practical language. The types help the compiler figure out optimisations, apart form further ensuring correctness. (But, that isn't the only way -- clojure is pure, but does not have as strong a type system as Haskell.)

If the type system is bothering you, I would suggest you to try a more dynamic language, like Scheme, or get around to using Haskell's type inference system.

0

Yes, the type system is an incredible asset. It would be very difficult to even describe how monads work or how some combinators operate without the type system. Consider how many tutorials on Haskell first ask you to consider the type of the function in question with a :t at the REPL. That is simply not available to you in a dynamically typed language. Sure, all the complexity of the type system is still there. A monad is still a monad. But the language has decided to wash its hands of the matter and not provide any help at all. You're on your own, pal. I'm not knocking dynamically typed languages. I love them dearly. Scheme is a power tool par excellance. But you'll notice that when we talk about things like monads in dynamic languages, we often invent a notation for describing the type of procedures. A functional programmer will battle with types one way or the other. Haskell's type checker just gives you good tools to learn how to do that.

Not the answer you're looking for? Browse other questions tagged or ask your own question.