Instance but no instance

I am trying to upgrade some update facility in my program to allow for IO: class Updater modelType updateType where update :: updateType -> modelType -> Maybe modelType class UpdaterIO modelType updateType where updateIO :: updateType -> modelType -> IO (Maybe modelType) pureUpdateToIO :: (updateType -> modelType -> (Maybe modelType)) -> updateType -> modelType -> IO (Maybe modelType) pureUpdateToIO updateFunction update model = return $ updateFunction update model instance (Updater modelType updateType) => UpdaterIO modelType updateType where updateIO = pureUpdateToIO update My code still works for all my old Updater instances even when I use them in the IO monad: do maybeUpdatedModel <- updateIO newUpdate oldModel So far so good. However, when I try to upgrade one of the Updater instances to an UpdateIO instance I get into a kind of a catch 22 situation where not only maybeUpdatedModel = update newUpdate oldModel results in a "No instance for Updater [...] [...]" compiler error as expected, but also do maybeUpdatedModel <- updateIO newUpdate oldModel unexpectedly results in an "Overlapping instances for UpdaterIO [...] [...]" compiler error. Where one of the overlapping instance declarations is: instance (Updater modelType updateType) => UpdaterIO modelType updateType How is that possible? Cheers, Jeroen

On Mon, Oct 18, 2010 at 09:31:31AM +0200, Jeroen van Maanen wrote:
unexpectedly results in an "Overlapping instances for UpdaterIO [...] [...]" compiler error. Where one of the overlapping instance declarations is:
instance (Updater modelType updateType) => UpdaterIO modelType updateType
When doing instance selection, GHC only looks at the part to the right of the =>. So, the instance above essentially means "every pair of types are an instance of UpdaterIO, and, oh yes, they had better be an instance of Updater as well". So the above instance overlaps with *every* other instance of UpdaterIO. There are a few solutions I can think of. One is to decide you are OK with the overlapping instances (in this case I think it ought to work correctly). Or you can bite the bullet and make a separate instance of UpdaterIO for all the old instances of Updater. -Brent
participants (2)
-
Brent Yorgey
-
Jeroen van Maanen