如何在Haskell 98中为特定类型的应用程序定义实例?

时间:2016-08-05 18:29:43

标签: haskell typeclass

我注意到Data.Set的测试套件只为Arbitrary Set a明确定义了a ~ Int,但为了避免使用GHC特殊~

instance Enum a => Arbitrary (Set a)

如何确保仅使用Arbitrary (Set Int)实例而无需任何GHC扩展?在仅限GHC的代码中,我使用FlexibleInstancesGADTs,然后使用

instance Arbitrary (Set Int)

instance a ~ Int => Arbitrary (Set a)

1 个答案:

答案 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 ...