import Control.Monad.Fix
import Data.IORef
import Prelude hiding (traverse)

data N a = N (IORef Bool, N a, a, N a)

newNode :: N a -> a -> N a -> IO (N a)
newNode b c f = do v  <- newIORef False
                   return (N (v, b, c, f))

ll = mdo n0 <- newNode n3 0 n1
         n1 <- newNode n0 1 n2
         n2 <- newNode n1 2 n3
         n3 <- newNode n2 3 n0
         return n0

data Dir = F | B deriving Eq

traverse :: Dir -> N a -> IO [a]
traverse d (N (v, b, i, f)) =
    do visited <- readIORef v
       if visited
          then return []
          else do writeIORef v True
                  let next = if d == F then f else b
                  is <- traverse d next
                  return (i:is)

l2dll :: [a] -> IO (N a)
l2dll (x:xs) = mdo c      <- newNode l x f
                   (f, l) <- l2dll' c xs
                   return c

l2dll' :: N a -> [a] -> IO (N a, N a)
l2dll' p []     = return (p, p)
l2dll' p (x:xs) = mdo c      <- newNode p x f
                      (f, l) <- l2dll' c xs
                      return (c, l)
