[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