Daniel Wagner の回答のオープン バリアントでは、 a を使用しTypeFamily
て、クラスを実装する各型が必要なコンテキストを指定できるようにします。
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
import GHC.Exts (Constraint)
import Data.Proxy
data Dict c where
Dict :: c => Dict c
このクラスにより、各タイプは、Ctx a
そのタイプに必要な追加の制約を指定できます。このcdict
関数は、コンテキストを強制的に従わせ、基礎となるを for eg プロダクトに含めずC
に取得する方法を提供し ます。Ctx
Ctx
class C a where
type Ctx a :: Constraint
cdict :: Proxy a -> CDict a
ACDict
はDict
、制約と型が必要とするC a
追加のコンテキストの両方を保持する a です。Ctx a
a
type CDict a = Dict (C a, Ctx a)
インスタンスはInt
余分なコンテキストを必要としません
instance C Int where
type Ctx Int = ()
cdict _ = Dict
タプル インスタンスにはC a
との両方が必要ですC b
instance (C a, C b) => C (a, b) where
type Ctx (a, b) = (C a, C b)
cdict _ = Dict
fstCDict
タプルについて書くことができます。
fstCDict :: forall a b. CDict (a, b) -> CDict a
fstCDict Dict = case cdict (Proxy :: Proxy a) of Dict -> Dict
不適切なインスタンス
C
魔法のようにインスタンスを呼び出すShow
インスタンスの間違ったインスタンスを書き込もうとすると、
instance (C a) => C (Maybe a) where
type Ctx (Maybe a) = (C a, Show a)
cdict _ = Dict
コンパイルエラーになります
Could not deduce (Show a) arising from a use of `Dict'
from the context (C a)
bound by the instance declaration ...
Possible fix:
add (Show a) to the context of the instance declaration
In the expression: Dict
In an equation for `cdict': cdict _ = Dict
In the instance declaration for `C (Maybe a)'