Haskell Example For Mutability On Objects

Before I answer this, I have a question. Does Haskell allow for mutability on objects? Once upon I time I remember it didn't. Does it still disallow this? AnswerMe please. -- DaveFayram

Depends on what do you call mutability on objects ;-) Actually this question is pretty easy to answer. HaskellLanguage have FirstClass variables in the form of IORef values. Also it is a language where code has ReferentialTransparency, so we need to thread (i.e. introduce explicit ordering) operations that have side-effects. These two things leads us to the fact that every expression dealing with IORefs has an IO type and they live inside the IO monad. While this may sound complicated it's actually simple. We can create a point object and imperatively update it:

 -- Defines the point data-type with two variables.
 data Point = XY {x :: IORef Int, y :: IORef Int}

-- Creates a new point from a pair of coordinates. -- As it uses variables it should use (monadic) do-notation newPoint (x, y) = do xRef <- newIORef x yRef <- newIORef y return (XY xRef yRef)

-- Imperatively updates the point's coordinates movePoint (deltaX, deltaY) (XY x y) = do modifyIORef x (+ deltaX) modifyIORef y (+ deltaY)

-- Prints the point to the standard output printPoint (XY x y) = do x' <- readIORef x y' <- readIORef y print (x', y')

-- simple test do p <- newPoint (1, 2) printPoint p movePoint (3, 2) p printPoint p

-- The result is as expected: (1,2) (4,4)

As you can see HaskellLanguage allows mutability on objects. While I agree the operation names could be a little bit better (e.g. readIORef/writeIORef vs. read/write vs. get/set) the idea is simple (also you can write alias to these functions if you prefer simpler names). Also you don't need to grok monads to understand this code, but groking monads is much more enlightening than groking design patterns IMHO.

I grok monads now. However, they seem inelegant to me. The minute you devote this much time and effort to add such a fundamental concept as "state", I feel you've been told by the underlying math, "No. This is a bad idea." That aside...

Monads weren't created to deal with "state", but they can be used to do so. IMHO you do not grok monads, otherwise you would know that. For example monads can be used to model any kind of computation, including: IO, state, parsing, implicit parameters, logging, non-determinism, exceptions, continuations with call/cc and combinations of such.

Wait wait wait, so you're saying that Monads were not part of the effort to integrate stateful operations like IO into purely functional systems?

Monads came from category theory, they weren't "invented" to solve programming languages issues. There are several models of IO that respect referential transparency, including UniquenessTypes, monads, stream-based io and ContinuationPassingStyle. Some time later PhillipWadler? wrote the paper "Monads for functional programming" where he showed how to write monads to structure functional programs and include different forms of effects (i.e. computations). The examples showed exceptions, state threading, output, non-determinism and parser combinators. After the Haskell designers decided to use a IO monadic solution (IIRC the previous IO framework in Haskell was stream-based).

View edit of March 5, 2008 or FindPage with title or text search