nulvinge
nulvinge

Reputation: 1598

Haskell: Overlapping instances of pair with same pair specialization

(Using comments for easier copy and pasting)

--Say I have the following monad:

{-# LANGUAGE GADTs, FlexibleInstances #-}

data Instruction b where
  Write :: a -> Instruction ()
  Write2 :: (a,a) -> Instruction ()
  Read :: Instruction a
  Read2 :: Instruction (a,a)
  Bind :: Instruction a -> (a -> Instruction b) -> Instruction b
  Return :: a -> Instruction a

instance Monad Instruction where
  (>>=) = Bind
  return = Return

--And the following class:

class Box a where
  write :: a -> Instruction ()
  read  :: Instruction a

instance Box Int where
  write = Write
  read  = Read

instance Box Float where
  write = Write
  read  = Read

instance (Box a,Box b) => Box (a,b) where
  write (a,b) = do
    write a
    write b
  read = do
    a <- Read
    b <- Read
    return (a,b)

instance (Box a) => Box (a,a) where
  write = Write2
  read = Read2

--Now, this works kind of fine, as long as I do not use the overlap:

test = do
  let i = 0 :: Int
  let f = 0 :: Float
  write (i,f)
  --But i get an overlapping instance for the following (understandably):
  write (i,i)

Is it possible to write this kind of class that will do the "right thing"? That is, how do I change the program such that the right instance is chosen.

I think I know of one runtime solution, but that won't be as nice.

I've seen rewrite rules, is that a good solution?

Upvotes: 1

Views: 158

Answers (1)

Satvik
Satvik

Reputation: 11208

You can use OverlappingInstances pragma in this case as Box (a,a) is more specific than Box (a,b) so compiler will choose the right instance for you.

Informally, you say a is more specific than b if you can instantiate b to a. Another definition can be, if you unify a and b you get a. For example, in (a,b) you can put b=a, so (a,a) is more specific than (a,b).

If compiler can not find the most specific instance it will throw error even with OverlappingInstances.

Upvotes: 3

Related Questions