2016-08-05 74 views
7

我注意到,測試套件Data.Set只有真正定義Arbitrary Set a理智的a ~ Int,但要避免GHC特殊~它採用如何在Haskell 98中爲特定類型應用程序定義實例?

instance Enum a => Arbitrary (Set a) 

我怎樣才能確保無需任何GHC擴展僅使用Arbitrary (Set Int)實例?在GHC-唯一代碼,我會使用任何FlexibleInstancesGADTs然後要麼

instance Arbitrary (Set Int) 

instance a ~ Int => Arbitrary (Set a) 

回答

6

這是可能使用的想法,我覺得我第一次在一份文件由奧列格Kiselyov遇到,這是Control.Lens.Equality的基礎。現在

import Data.Functor.Identity 

class IsInt a where 
    fromIntF :: f Int -> f a 

instance IsInt Int where 
    fromIntF fx = fx 

toIntF :: IsInt a => g a -> g Int 
toIntF = unf . fromIntF . F $ id 

newtype F g a b = F {unf :: g b -> a} 

fromInt :: IsInt a => Int -> a 
fromInt = runIdentity . fromIntF . Identity 

toInt :: IsInt a => a -> Int 
toInt = runIdentity . toIntF . Identity 

我可以使用

instance IsInt a => Arbitrary (Set a) 

,並且相信我真的處理Int。爲方便起見,我可以用我需要的任何類,其中Int是一個實例約束IsInt類:

class (Show a, Read a, Integral a, Arbitrary a) => IsInt a where ... 
+3

這可能是值得一提:這給你的系統之外你想要的保障,而不是在它裏面。也就是說,GHC不會從'IsInt a'推斷出'a〜Int'。這偶爾會需要煩人的附加類型註釋。儘管如此,我認爲H98(或H2010)完全可以幫到你。 –

+0

@DanielWagner,是的,它肯定不如GHC的方法。如果平等限制是標準化的,我一定會更喜歡他們。但「容器」通常儘可能地「可移植」,所以如果我能夠做到沒有擴展所需要的東西,我會的。 – dfeuer

+1

@DanielWagner,我認爲值得注意的是,這個實現與GHC兼容,因爲你可以將'fromIntF'應用到'Refl :: Int:〜:Int'來獲得某種類型的'IsInt a => Int:〜 :a'。事實上,這將適用於任何類似的平等類型,無論它如何適用於該語言。 – dfeuer

相關問題