
On 2004 October 08 Friday 09:57, John Goerzen wrote:
defaultHandler :: LogHandler b => IO (a -> IORef b) defaultHandler = do h <- (streamHandler stdout WARNING) r <- newIORef h return (\x -> r)
The idea is to create a new IORef to something in the LogHandler class and return a function that returns it. The thing returned by that call to streamHandler is in the LogHandler class. Specifically, its declaration looks like this:
instance LogHandler (GenericHandler a) where
defaultHandler returns its result for _some_ LogHandler type, while the type declaration
defaultHandler :: LogHandler b => IO (a -> IORef b) has an implicit universal interpretation of b. To satisfy this type declaration, defaultHandler would have to be able to return a handler for _any_ LogHandler type, depending on the context in which defaultHandler is called.
The Haskell type for defaultHandler uses an existential type, and would look like this: data SomeLogHandler = forall a . (LogHandler a) => SomeLogHandler a defaultHandler :: IO (a -> IORef SomeLogHandler) defaultHandler = do h <- (streamHandler stdout WARNING) r <- newIORef (SomeLogHandler h) return (\x -> r) Then you would use it as f <- defaultHandler SomeLogHandler h <- readIORef (r 0) ... use the LogHandler h ... By the way, when you say "return a function that returns it", I suspect you are thinking of how this would work in C or Java, where to accomplish anything you need to call a function or invoke a method. If the function parameter of type 'a' serves no useful purpose, then the above can be simplified to data SomeLogHandler = forall a . (LogHandler a) => SomeLogHandler a defaultHandler :: IO (IORef SomeLogHandler) defaultHandler = do h <- (streamHandler stdout WARNING) r <- newIORef (SomeLogHandler h) return r Then you would use it as f <- defaultHandler SomeLogHandler h <- readIORef r ... use the LogHandler h ...