[Haskell-cafe] A use case for *real* existential types
Andres Löh
andres at well-typed.com
Fri May 10 15:00:43 CEST 2013
Hi.
> So the natural question here is if we can employ the type system to enforce
> this correspondence. Phantom types immediately come to mind, as this
> problem is almost the same as ensuring that STRefs are only ever used in a
> single ST computation. The twist is that the inotify interface has nothing
> analogous to runST, which does the "heavy lifting" of the type magic behind
> the ST monad.
>
> This twist is very simple to deal with if you have real existential types,
> with the relevant part of the interface looking approximately like
>
> init :: exists a. IO (Inotify a)
> addWatch :: Inotify a -> FilePath -> IO (Watch a)
> rmWatch :: Inotify a -> Watch a -> IO ()
You can still do the ST-like encoding (after all, the ST typing trick
is just an encoding of an existential), with init becoming "like
runST":
> init :: (forall a. Inotify a -> IO b) -> IO b
> addWatch :: Inotify a -> FilePath -> IO (Watch a)
> rmWatch :: Inotify a -> Watch a -> IO ()
Looking at your inotify.hs, the code of init becomes:
> init :: (forall a. Inotify a -> IO b) -> IO b
> init k = do
> nextWatchRef_ <- newIORef 0
> currentWatchesRef_ <- newIORef []
> k $ Inotify {
> nextWatchRef = nextWatchRef_
> , currentWatchesRef = currentWatchesRef_
> }
And the code of main becomes:
> main = init $ \ nd0 -> do
> wd0 <- addWatch nd0 "foo"
> wd1 <- addWatch nd0 "bar"
> init $ \ nd1 -> do
> 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
Cheers,
Andres
--
Andres Löh, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com
More information about the Haskell-Cafe
mailing list