2

数値型、より具体的には a に制約したいパラメーター化された型がありますFractional

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

そのため、API のユーザーは、使用する可能性のある非整数型 (FloatまたはDouble?) を定義できますが、私が作成した内部 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'

これは、私がおそらくやり続けたくないことをしていることを示唆しています。つまり、私のデザインはゴミです。

私はこの API で次のことを言おうとしていると思いますFractional。どうすればこれを達成できますか? または、私は的外れであるか、および/または過剰に設計されていますか?

4

2 に答える 2

2

エラーが示すように、次の方法でこれを行うことができますGADTs

{-# LANGUAGE GADTs, StandaloneDeriving #-}

data Rating a where
    Score :: (Fractional a) => a -> Rating a
    Unscored :: Rating a

deriving instance (Show a) => Show (Rating a)
deriving instance (Eq a) => Eq (Rating a)

-- No need for a context here!
halfScore :: Rating a -> Rating a
halfScore (Score a) = Score (a / 2)
halfScore Unscored = Unscored

StandaloneDerivingGHC は派生できないためShowEqそうでない場合は GADT のために必要です。

于 2016-02-23T11:47:40.843 に答える