StateTのバージョンは、一見すると正しいように見えます。残念ながら、RMonadet。al。ほぼすべてを複製する必要があります。私はSuitableを使用してコードを書き始めましたが、重複が多すぎたために諦めました(そして、結局、私はそれを本当に必要としませんでした)。
編集:
どのように機能するかについての私の記憶からSuitable
、それは次のようなものです:
Functor
クラスについて考えてみましょう。追加の制約Set
が必要なため、そのインスタンスにすることはできません。Ord
素朴なアプローチは次のようになります。
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import qualified Data.Set as S
class MyFunctor c a | c -> a where
myfmap :: (MyFunctor c b) => (a -> b) -> c a -> c b
instance (Ord a) => MyFunctor S.Set a where
myfmap = S.map
ただし、これにより次のエラーが返されます。
Error: test.hs:11:16: Could not deduce (Ord b) arising from a use of `S.map'
from the context (Ord a)
bound by the instance declaration at /tmp/test.hs:10:10-37
or from (MyFunctor S.Set b)
bound by the type signature for
myfmap :: MyFunctor S.Set b => (a -> b) -> S.Set a -> S.Set b
at /tmp/test.hs:11:7-20
Possible fix:
add (Ord b) to the context of
the type signature for
myfmap :: MyFunctor S.Set b => (a -> b) -> S.Set a -> S.Set b
or the instance declaration
In the expression: S.map
In an equation for `myfmap': myfmap = S.map
In the instance declaration for `MyFunctor S.Set a'
どうしてこれなの?これは、制約がインスタンスレベルで保持または検出されないため、GHCは、を使用するときにに制約myfmap
があるはずであることを認識していません。Ord
b
このSuitable
タイプは、次の種類の制約を指定できる制約ディクショナリを明示的に作成するために使用されます。
import Data.Suitable
import qualified Data.Set as S
class MyFunctor c where
myfmap :: (Suitable c a, Suitable c b) => (a -> b) -> c a -> c b
instance MyFunctor S.Set where
myfmap f s = withConstraintsOf s
$ \ SetConstraints
-> withResConstraints $ \ SetConstraints -> S.map f s
(ここでSetConstraints
はすでに定義されていData.Suitable
ます)
この実装は機能しますが、型シグネチャが少し複雑になり、メソッドの実装が少し複雑になります(ここでは、2回(1回は、、もう1回は)を取り込む必要があることに注意してくださいSetConstraints
)。制約のない型の場合、制約関数は必要ないことに注意してください。Set a
Set b
Suitable
Typeclassopediaでクラスのバージョンを作成しようとし始めましSuitable
たが、インスタンスがかなり毛むくじゃらになったため、あきらめました。