DeMonad

At my second year of university i made a project for the “Programming Languages” course. It consisted in a simple program written in Haskell to eliminate a Monad from the code.
It exactly rewrites another piece of haskell code containing the definition of one single monad, and rewrites it without it.
The monad must be user defined, it is no possible to remove the IO monad for instance.
A current limitation is the monad must be defined in the file to rewrite, not that is a big limitation thought.

But an example is better then words…
This code uses a list as state, and gives the user 2 functions, insertList to insert a list, and getElement to get an element from the list.

data Test a = Test (TestS -> (a,TestS))

instance Monad Test where
    return a      = Test (\s -> (a,s))
    Test f >>= gm = Test (\s0 -> let (x,s1) = f s0
                                     (Test g) = gm x
                                   in g s1)

insertList l = Test (\s0 -> ((),l))
getElement n = Test (\(l) -> (l!!n,l))

runTest :: TestS -> Test a -> a
runTest s0 (Test c) = fst $ c s0

testcode = do h <- getElement 5
              p <- getElement 4
              t <- getElement 2
              return p

test = runTest [0..] testcode

Then, after passing it to the DeMonadizer

ghc --make Main.hs DeMonad.hs
./Make test.hs

the code looks like this (it’s ugly, i know)

module Test where

type TestS = [Int]

data Test a = Test (TestS -> (a, TestS))
insertList l = Test (\ s0 -> ((), l))
getElement n = Test (\ (l) -> (l !! n, l))

runTest :: TestS -> Test a -> a
runTest s0 (Test c) = fst $ c s0
testcode
  = (\ (Test f) ->
       Test
         (\ s0 ->
            let (x, s1) = f s0
                (Test g)
                  = (\ h ->
                       (\ (Test f) ->
                          Test
                            (\ s0 ->
                               let (x, s1) = f s0
                                   (Test g)
                                     = (\ p ->
                                          (\ (Test f) ->
                                             Test
                                               (\ s0 ->
                                                  let (x, s1) = f s0
                                                      (Test g) = (\ t -> Test (\ s -> (p, s))) x
                                                    in g s1))
                                            (getElement 2))
                                         x
                                 in g s1))
                         (getElement 4))
                      x
              in g s1))
      (getElement 5)
test = runTest [0 ..] testcode

As you can see the monad definition is gone, and with it also the do syntax.

This solution allowed some haskell code to run as curry code!
It is very similar in syntax, but it is a funcional-logic programming language, and as such it has non-determinism (and everybody should love the magic of =:=). The code is rather long, since it must provide the language with actions for each of his syntactical elements, it can be found at his code page.

Advertisements

, , , , , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: