2016-08-05 22 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

相关问题