There are problems with this approach... Instance heads are only chosen by the pattern not the constraints, so:

instance (Ord a, Num a) => ApproxEq a where x ~= y = (abs (x-y) < 1)

Will match any type at all (whether a member of Ord or Num or not) and then will
fail if the particular type is not an instance of Ord or Num.


Using incoherent-instances is almost certainly broken as it just stops the compiler complaining is a generic instance (like above) overlaps with a specific instance in the wrong way. Using the flag just makes GHC silently choose the _most_generic_instance_. Almost alwaysApproxEq we want the opposite behaviour and want GHC to choose the most specific instance in the case of overlap.

However it should do what you want with just -foverlapping-instances -fundecidable-instances.


   Keean.

Christian Maeder wrote

Blair Fraser wrote:

I'm new to haskell and I'm working through the class section of the
gentle tutorial.  I decided to implement an ApproxEq class (just for
fun), but have run into problems.  The code below works fine for units
and bools, but gives an unresolved overloading error for Floats and
Doubles.  What's going on here?  What does the error message mean and
what did I do wrong?  (I'm in Hugs.)

-- ApproxEq: My first class.
class (Eq a) => ApproxEq a where
  (~=) :: a -> a -> Bool
  x ~= y = x == y -- By default, check equality

-- These two override default with same, just checking if it works
instance ApproxEq () where () ~= () = True instance ApproxEq Bool where x ~= y = x == y


-- These two override default with different
--   consider floating points equal if they differ by one or less
instance ApproxEq Float where x ~= y = (abs (x-y) <= 1)
instance ApproxEq Double where x ~= y = (abs (x-y) <= 1)


More elegant seems to be:

instance (Ord a, Num a) => ApproxEq a where x ~= y = (abs (x-y) < 1)

However, this requires extensions to "Allow unsafe overlapping instances":

hugs -98 +O

ghci -fglasgow-exts -fallow-overlapping-instances -fallow-undecidable-instances -fallow-incoherent-instances

-- This one dosn't work either, but it just depends on the other two
instance ApproxEq a => ApproxEq [a] where
  [] ~= [] = True
  (x:xs) ~= (y:ys) = x ~= y && xs ~= ys
  _ ~= _ = False

Thanks,
Blair


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to