The Russian Doll Pattern in Haskell [ 2010-05-12 05:56:18 UTC ]

The Russian Doll Pattern occurs when functions replace themselves. The example in that link uses javascript, but this technique should be applicable to any language with first-class functions and mutable containers.

nesting robots

Even haskell, with its static types and referential transparency, is capable of emulating this pattern. Here's an example:

-- RussianDoll.hs -- Russian Doll principle in haskell module Main where import Control.Concurrent.MVar import Control.Monad (join) main :: IO () main = do fn <- newEmptyMVar putMVar fn $ do putStrLn "First!" swapMVar fn (putStrLn "Again!") >> return () join $ readMVar fn join $ readMVar fn join $ readMVar fn

Which when executed prints:

First! Again! Again!

An empty MVar is created and bound to fn. MVars are especially convenient for this example since they have an empty state built-in. The first time fn is executed, "First!" is printed, but then the fn MVar is swapped for a new action that prints "Again!".

The inferred type for fn is MVar (IO ()), so join can be used to execute the IO () action inside the MVar.

ghci> :t join join :: (Monad m) => m (m a) -> m a

which means

:t join (readMVar (undefined :: (MVar (IO ())))) join (readMVar (undefined :: (MVar (IO ())))) :: IO ()

Neat!

It's usually a better idea in these cases to use the shared mutable state to delegate to functions instead of storing and swapping the functions themselves. I am however optimistic that this approach could be used in some code to build a more beautiful abstraction.