1

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

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

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

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

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

4

1 回答 1

3

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

非正式地说,你说a的比b你可以实例化b的更具体a。另一个定义可以是,如果你统一ab得到a. 例如,在(a,b)你可以放b= a,所以(a,a)(a,b).

如果编译器找不到最具体的实例,即使使用OverlappingInstances.

于 2013-08-27T13:46:23.520 回答