
Svein Ove Aas wrote:
Martin Huschenbett wrote:
instance (Show a,Read a) => Binary a where put = put . show get = fmap read get But then you will need the following language extensions: FlexibleInstances, OverlappingInstances, UndecidableInstances
Well, isn't there a good chance it'll end up picking that instance even when a more specific one is available, then?
I think the problem here is that I don't know of any way to inform GHC that any particular instance is "less specific".
OverlappingInstances will allow more specific instances to be defined, and will select them when appropriate. Where "specific" has to do with the usual type unification algorithm. This instance is on a type variable, hence is the least specific. An instance on (Maybe a), (Either a b), etc would all be more specific. Instances on (Maybe Int), (Either Bool b), (Either a Double) would be more specific still. Aside: Depending on how you're using this, we can run into problems with, say, (Either Bool Double). Does it fall under (Either Bool b) or under (Either a Double)? By default, OverlappingInstances requires that you manually resolve this diamond issue (i.e. by defining an instance for (Either Bool Double) which is more specific than all other options). The IncoherentInstances option tells the compiler to deal with the ambiguity itself, which means it will pick the most specific instance which does not introduce ambiguity (i.e. the other end of the diamond; in this case, the instance for the fully unspecified type variable). Obviously, incoherence generally does not mean what you want. The UndecidableInstances is because the two elements of the context are not "smaller" than the head (Binary a), and hence the compiler cannot guarantee that progress is being made when it backward-chains to find those instances. To witness why this could be a problem, imagine an instance for Show or Read which took Binary in the context. -- Live well, ~wren