
Thanks so much for all the help many of you have provided. I have one (heh) more question: I have this code: 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 ... and streamHandler returns a "GenericHandler Handle" object. Now, when compiling that defaultHandler code, the compiler complains: Cannot unify the type-signature variable `b' with the type `MissingH.Logging.Handler.Simple.GenericHandler Handle' Expected type: IORef b Inferred type: IORef (MissingH.Logging.Handler.Simple.GenericHandler Handle) In a lambda abstraction: \ x -> r In the first argument of `return', namely `(\ x -> r)' I'm stumped. Can anyone shed some light on that for me? Thanks, -- John

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 ...
participants (2)
-
John Goerzen
-
Scott Turner