我可以在Haskell中约束类型/数据构造函数的参数化多态类型吗?

Ale*_*lex 1 haskell types api-design parametric-polymorphism

我有一个参数化类型,我想约束到一个数字类型,更具体地说是一个Fractional,例如:

data Rating a = (Fractional a) => Score a | Unscored deriving (Show, Eq)
Run Code Online (Sandbox Code Playgroud)

这样API的用户可以定义他们可能使用哪种非整数类型(FloatDouble?),但我写的内部API代码仍然可以对数字类型执行算术运算.我不希望它是一个整数,因为我的"内部操作"的结果可能不是整数,我的理解是使用Fractional会导致更准确的结果.

编译上面(至少在GHCI中)给出了以下错误:

    Data constructor `Score' has existential type variables, a context, or a specialised result type
  Score :: forall a. Fractional a => a -> Rating a
  (Use ExistentialQuantification or GADTs to allow this)
In the definition of data constructor `Score'
In the data declaration for `Rating'
Run Code Online (Sandbox Code Playgroud)

这告诉我,我正在做一些我可能不想继续尝试的事情; 即我的设计是垃圾.

我想我试图在这个API中说出以下内容:"当你使用Rating类型时,它的参数必须是一个子类,Fractional所以我可以对它执行准确的算术".我怎么能实现这个目标?还是我离开了标记和/或过度工程?

Twa*_*ven 5

您不应该将Fractional约束放在数据类型上,而应放在使用它的函数上.所以

data Rating a = Score a | Unscored deriving (Show, Eq)

makeSomeRating :: Fractional a => a -> Rating a
makeSomeRating x = Score (x / 2) -- can use Fractional functions here

doSomethingElseWithRating :: Fractional a => Rating a -> Something
Run Code Online (Sandbox Code Playgroud)