2013-02-02 30 views
3

我有一些代碼使用類型來消除實例的歧義(真正的代碼是使用GHC.TypeLits類型標記的singletons,但我認爲這不是密切相關的),我想使用let綁定來避免文本級別的重複;不幸的是,這會使結果單調。避免在沒有類型註釋的情況下綁定的單態

以下是問題的一個例子:

class Foo a where 
    foo :: a 

instance Foo Int where 
    foo = 0 

instance Foo Char where 
    foo = 'a' 

data Bar a = Bar String 
    deriving (Show) 

bar :: forall a. (Show a, Foo a) => a -> Bar a 
bar _ = Bar $ show (foo :: a) 

idInt :: Bar Int -> Bar Int 
idInt = id 

idChar :: Bar Char -> Bar Char 
idChar = id 

main = let quux = bar undefined in 
    print (idInt quux) >> print (idChar quux) 

上面的代碼不編譯(但是,當然,如果我輸入註釋quux是多態的,一切工作正常),正確地抱怨它不能匹配IntChar。有沒有什麼辦法可以編譯成功,而不需要鍵入註釋,也不需要在每個使用站點重複bar undefined

回答

6
{-# LANGUAGE NoMonomorphismRestriction #-} 

或者,如果你想少全球

let quux() = bar undefined in 
    print (idInt (quux()) >> print (idChar (quux())) 

的原因,後者的作品是,當他們沒有參數傳遞給等號左邊的綁定只能monomorphised東西。

let foo = \x y -> x + y -- :: Integer -> Integer -> Integer 
let bar x y = x + y  -- :: (Num a) => a -> a -> a 

因此得到quux不monomorphize,你必須給它一個參數傳遞給等號的左邊。如果quux不是一個值,而是一個功能,你可以簡單地ETA擴大來獲得同樣的效果:

let quux x = bar undefined x in ... 

對於前者,不用擔心性能 - 如果你一直稱呼其爲quux(),則將被內聯並生成與具有顯式類型簽名的版本相同的代碼。

+0

我認爲'NoMonomorphismRestriction'只適用於頂級綁定。呵呵。讓我感到驚訝的是運行代碼。 –

相關問題