Haskell:具有相同对专业化的重叠实例

时间:2013-08-27 12:58:46

标签: haskell types gadt

(使用注释更容易复制和粘贴)

--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)

是否有可能写出这种能做“正确的事”的课程? 也就是说,如何更改程序以便选择正确的实例。

我想我知道一个运行时解决方案,但这不会那么好。

我见过重写规则,这是一个很好的解决方案吗?

1 个答案:

答案 0 :(得分:3)

在这种情况下,您可以使用OverlappingInstances pragma,因为Box (a,a)Box (a,b)更具体,因此编译器会为您选择正确的实例。

非正式地,如果您可以将a实例化为b,则表示ba更具体。另一个定义可能是,如果您统一ab,则会获得a。例如,在(a,b)中,您可以b = a,因此(a,a)(a,b)更具体。

如果编译器找不到最具体的实例,即使使用OverlappingInstances也会抛出错误。