haskell-fswatch / hfsnotify

Unified Haskell interface for basic file system notifications
BSD 3-Clause "New" or "Revised" License
136 stars 40 forks source link

Potential Cleanup for Duplication - Native and Polling #31

Closed dmbarbour closed 11 years ago

dmbarbour commented 11 years ago

I find the repeated 'either nativeImpl pollingImpl' code in System.FSNotify a little irritating. Fortunately, it would be easy to eliminate, e.g. by shifting away from a typeful model to something closer to:

data Session wd = Session 
    { killSession :: IO ()
    , killListener :: wd -> IO ()
    , listen :: WatchConfig -> FilePath -> ActionPredicate -> EventChannel -> IO wd
    , listenRecursive :: WatchConfig -> FilePath -> ActionPredicate -> EventChannel -> IO wd
    } 

Then using Rank2Types to hide wd.

type Listener = forall wd. Session wd
initNative :: IO (Maybe Listener)

Potentially, we can also eliminate listenRecursive since I'm working on a new Event type that carries isDir information. We'd need to make the Session type independent of channels. But we can simplify it to:

data Session wd = Session 
    { killSession :: IO ()
    , killListener :: wd -> IO ()
    , listen :: FilePath -> (Event -> IO ()) -> IO wd
    } 

And then introduce channels and Debounce externally.

None of this would be observable to a client of FSNotify.

dmbarbour commented 11 years ago

Of course, even easier would be:

data Session = Session 
    { killSession :: IO ()
    , killWatch :: FilePath -> IO ()
    , initWatch :: FilePath -> (Event -> IO ()) -> IO ()
    } 

With an explicit assertion that there is only one active watch per FilePath per Session. No fancy types required.

I like this option because Linux's inotify doesn't support more than one action per inotify 'session' anyway. If we want FSNotify to be portable (which is the point, right?) then we'll need to accommodate the lowest common denominator.