问题
Wen using functional dependencies, I frequently hit the Coverage Condition. It is possible to lift it with UndecidableInstances
, but I usually try to stay away from that extension.
Here is a somewhat contrived example, that works without UndecidableInstances
:
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
data Result = Result String
deriving (Eq, Show)
data Arguments a b = Arguments a b
class Applyable a b | a -> b where
apply :: a -> b -> Result
instance Applyable (Arguments a b) (a -> b -> Result) where
(Arguments a b) `apply` f = f a b
When I make the result type more generic, the Coverage Condition fails (hence requiring UndecidableInstances
):
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Result a = Result a
deriving (Eq, Show)
data Arguments a b = Arguments a b
class Applyable a b c | a -> b c where
apply :: a -> b -> Result c
instance Applyable (Arguments a b) (a -> b -> Result c) c where
(Arguments a b) `apply` f = f a b
I thought that because b
and c
are both determined by a
, the more generic code should not cause any problems, so my questions:
- Are there any possible issues with using
UndecidableInstances
here - Can I model the above scenario without relying on
UndecidableInstances
(maybe with type families?)
回答1:
There's no big reason to stay away from UndecidableInstances
. The worst that can happen is that the type checker starts looping (and tells you about it, I think). You can make the coverage condition more and more clever, but it will never do everything you could want since that's undecidable.
来源:https://stackoverflow.com/questions/9076179/how-to-get-around-the-coverage-condition-for-functional-dependencies-without-usi