我注意到Data.Set
的测试套件只为Arbitrary Set a
明确定义了a ~ Int
,但为了避免使用GHC特殊~
instance Enum a => Arbitrary (Set a)
如何确保仅使用Arbitrary (Set Int)
实例而无需任何GHC扩展?在仅限GHC的代码中,我使用FlexibleInstances
或GADTs
,然后使用
instance Arbitrary (Set Int)
或
instance a ~ Int => Arbitrary (Set a)
答案 0 :(得分:6)
这可以使用我认为我在Oleg 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
。为方便起见,我可以将IsInt
类限制为我需要的任何类Int
是一个实例:
class (Show a, Read a, Integral a, Arbitrary a) => IsInt a where ...