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

dfe*_*uer 7 haskell typeclass

我注意到,测试套件Data.Set只有真正定义Arbitrary Set a合理的a ~ Int,但要避免GHC特殊~,它使用

instance Enum a => Arbitrary (Set a)
Run Code Online (Sandbox Code Playgroud)

如何在Arbitrary (Set Int)不需要任何GHC扩展的情况下确保仅使用实例?在GHC-唯一代码,我会请使用FlexibleInstancesGADTs再任

instance Arbitrary (Set Int)
Run Code Online (Sandbox Code Playgroud)

要么

instance a ~ Int => Arbitrary (Set a)
Run Code Online (Sandbox Code Playgroud)

dfe*_*uer 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
Run Code Online (Sandbox Code Playgroud)

现在我可以用了

instance IsInt a => Arbitrary (Set a)
Run Code Online (Sandbox Code Playgroud)

并确信我真的在与之打交道Int.为方便起见,我可以IsInt使用我需要的任何类来限制类,这Int是一个实例:

class (Show a, Read a, Integral a, Arbitrary a) => IsInt a where ...
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是:这为您提供了系统外的保证,但不在其中.也就是说,GHC不会从'IsInt a'推断出'a~Int`.这有时可能需要恼人的附加类型注释.但我不认为纯粹在H98(或H2010)中可以帮助它. (3认同)