2013-08-27 28 views
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) 

是否有可能寫這種類的,會做「正確的事」? 也就是說,如何更改程序,以便選擇正確的實例。

我想我知道一個運行時解決方案,但那不會那麼好。

我見過重寫規則,是一個很好的解決方案嗎?

+0

你真的需要第二個例子嗎?我會認爲'Box(a,b)'只是'Box(a,a)'的一種更一般化的形式,除非你希望第二個不同於第一個。 – bheklilr

+0

如果不明顯,「Box(a,a)」使用「Write2」和「Read2」,這是不同的行爲。這是問題的全部。 – nulvinge

+0

您是否嘗試過'OverlappingInstances'語言編譯指示?看起來像你有類似的問題http://stackoverflow.com/a/1072523/839246。 – bheklilr

回答

3

在這種情況下,您可以使用OverlappingInstances編譯指示,因爲Box (a,a)Box (a,b)更具體,所以編譯器會爲您選擇正確的實例。

通俗地說,你說ab更具體的,如果你可以實例ba。另一個定義是,如果你統一ab,你會得到a。例如,在(a,b)中,您可以輸入b = a,因此(a,a)(a,b)更具體。

如果編譯器找不到最具體的實例,即使使用OverlappingInstances,它也會拋出錯誤。

+0

有趣。什麼是更具體的標準?在這種情況下,更具體的實例在更通用實例的集合內。如果它們只是重疊?那麼哪個實例最具體? – nulvinge

+0

@nulvinge http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/type-class-extensions.html – Satvik

+0

@nulvinge查看更新的答案。 – Satvik