ゲームライブラリを書いています。私はそれをインスタンスの階層で動作させています
class Animation a where
event :: a -> Event -> Writer [Event] a
paint :: a -> IO ()
Hereevent
はイベントを処理し、場合によってはその親が確認できるように新しいイベントを発行し (たとえば、出口Button
は を待ってMouseClickEvent
発行することができますCloseEvent
)、paint
描画を行います。私の一般的なユースケースは
--a user defined Animation, say a button
data MyChild = MyChild
instance Animation Child where
... anything
--a library defined Animation which is a composition of other animations
data LibWrapper = LibWrapper (Event -> Writer [Event] LibWrapper) (IO ())
mkWrapper :: (Animation a) => a -> LibWrapper
mkWrapper a = LibWrapper (\ev -> mkWrapper <$> event a ev) (paint a)
instance Animation LibWrapper where
event (LibWrapper e _) = e
paint (LibWrapper _ p) = p
--a user defined Animation for which the 'event' and 'paint' will be called
data MyRoot = MyRoot LibWrapper
instance Animation MyRoot where
event (MyRoot a) ev = MyRoot <$> event a ev
paint (MyRoot a) = paint a
game = MyRoot (mkWrapper Child)
ここで、カスタム イベントを許可します。あれは、
class Animation a e where
event :: a -> e -> Writer [e] a
paint :: a -> IO ()
問題は、 ( ) にさらに制限されたLibWrapper
( ) を含めることができないことです。私はパラメータ化して持ってみましたが、Haskell は の 2 つの出現を無関係なものと見なしているようで、どうすればよいかわかりません。instance Animation LibWrapper anyevent
MyChild
instance Animation MyChild MyEvent
LibWrapper
instance Animation (LibWrapper event) event
event
私も検討しました
class Animation a where
event :: a e -> e -> Writer [e] (a e)
paint :: a e -> IO ()
次に、それLibWrapper MyEvent
は a を含み、それでMyChild MyEvent
問題ありません。でも、もう定義する方法がありinstance MyChild MyEvent
ませんよね?
MyEvent
の型で指定したいのMyRoot
ですが、ライブラリモジュールにパラメーターとして渡す方法があれば、それも受け入れられます。
編集
質問を投稿したのと同じように、試してみました
class Animation a e where
event :: a e -> e -> Writer [e] (a e)
paint :: a e -> IO ()
...念のため。もちろん、うまくいきました。ここで行われている型マジックについてはまだよくわかりません。説明をいただければ幸いです。