[Haskell-cafe] Stuck on design problem

Nicolas Trangez nicolas at incubaid.com
Tue May 21 00:14:08 CEST 2013


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




More information about the Haskell-Cafe mailing list