import           Data.IORef

data Inotify a = Inotify
    { nextWatchRef      :: IORef Int
    , currentWatchesRef :: IORef [(Int,String)]
    } 

newtype Watch a = Watch Int

init :: exists a. IO (Inotify a)
init = do
  nextWatchRef_ <- newIORef 0
  currentWatchesRef_ <- newIORef []
  return Inotify { 
               nextWatchRef = nextWatchRef_
             , currentWatchesRef = currentWatchesRef_
             }

addWatch :: Inotify a -> String -> IO (Watch a)
addWatch nd filepath = do
  wd <- readIORef (nextWatchRef nd)
  writeIORef (nextWatchRef nd) (wd + 1)
  map <- readIORef (currentWatchesRef nd)
  writeIORef (currentWatchesRef nd) ((wd,filepath):map)
  return (Watch wd)

rmWatch :: Inotify a -> Watch a -> IO ()
rmWatch nd (Watch wd) = do
  map <- readIORef (currentWatchesRef nd)
  writeIORef (currentWatchesRef nd) (filter ((/= wd) . fst) map)

printInotifyDesc :: Inotify a -> IO ()
printInotifyDesc nd = print =<< readIORef (currentWatchesRef nd)


main = do
  nd0 <- init
  wd0 <- addWatch nd0 "foo"
  wd1 <- addWatch nd0 "bar"
  nd1 <- init
  wd3 <- addWatch nd1 "baz"
  printInotifyDesc nd0
  printInotifyDesc nd1
  rmWatch nd0 wd0
  rmWatch nd1 wd3
-- These lines cause type errors:
--  rmWatch nd1 wd0
--  rmWatch nd0 wd3
  printInotifyDesc nd0
  printInotifyDesc nd1


