(使用注释更容易复制和粘贴)
--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)
是否有可能写出这种能做“正确的事”的课程? 也就是说,如何更改程序以便选择正确的实例。
我想我知道一个运行时解决方案,但这不会那么好。
我见过重写规则,这是一个很好的解决方案吗?
答案 0 :(得分:3)
在这种情况下,您可以使用OverlappingInstances
pragma,因为Box (a,a)
比Box (a,b)
更具体,因此编译器会为您选择正确的实例。
非正式地,如果您可以将a
实例化为b
,则表示b
比a
更具体。另一个定义可能是,如果您统一a
和b
,则会获得a
。例如,在(a,b)
中,您可以b
= a
,因此(a,a)
比(a,b)
更具体。
如果编译器找不到最具体的实例,即使使用OverlappingInstances
也会抛出错误。