Adam, On Mon, 2013-05-20 at 13:37 +0100, Adam Gundry wrote: > Hi Nicolas, > > Your design doesn't look too unreasonable, though I haven't looked at in > detail. I do have a quick observation regarding the implementation that > I hope might help. Your gist defines > > > class MonadLog m a where > > getEntry :: Index -> m (Entry a) > > > > instance MonadLog (MemLog a) a > > and then you hit the error > > > No instance for (MonadLog (MemLog a0) ()) > > which is a tell-tale ambiguity problem. This is a common issue with > multi-parameter type classes. GHC cannot determine the existential > variable a0, because it will not commit to the instance for MemLog in > case a more specific instance turns up. > > One option is to turn on GADTs or TypeFamilies and write > > > instance a ~ a' => MonadLog (MemLog a) a' > > which will allow the instance to match and generate the easily solved > constraint a0 ~ (). You may need to do the same for other instances. > > Alternatively, you could add a functional dependency > > > class MonadLog m a | m -> a > > or use a type family: > > > class MonadLog' m where > > type Element m > > getEntry' :: Index -> m (Entry (Element m)) > > > instance MonadLog' (MemLog a) where > > type Element (MemLog a) = a > > getEntry' i = flip (IntMap.!) i `fmap` ask >
Thanks a bunch. Using FunDeps, things work as expected, also in my more complicated original code. I chose the FunDeps approach because it seems the least intrusive (no need to clutter instances). Thanks a bunch for all help, this list is certainly one of the things which makes writing Haskell code a very rewarding experience. Thanks, Nicolas _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe