Gtk2Hsバインディングを使用する小さなHaskellプログラムがあります。DrawingAreaをクリックすると、プログラムのウィンドウにポイント(小さな正方形)を描くことができます。
[...]
image <- builderGetObject gui castToDrawingArea "drawingarea"
p <- widgetGetDrawWindow image
gc <- gcNewWithValues p (newGCValues { foreground = Color 0 0 0,
function = Copy })
on image buttonPressEvent (point p gc)
set image [ widgetCanFocus := True ]
[...]
point :: DrawWindow -> GC -> EventM EButton Bool
point p gc = tryEvent $ do
(x', y') <- eventCoordinates
liftIO $ do
let x = round x'
let y = round y'
let relx = x `div` 4
let rely = y `div` 4
gcval <- gcGetValues gc
gcSetValues gc (newGCValues { function = Invert })
drawRectangle p gc True (relx * 4) (rely * 4) 4 4
gcSetValues gc gcval
試行錯誤の方法で、Hackageのドキュメントを読んだ後、ウィジェットはデフォルトでこのイベントのシグナルを提供しないため、ボタンを押すイベントを描画領域に追加することができました。ただし、EventMの定義と使用法がわからないため、ウィジェットに新しいイベントを再度追加する必要がある場合は、EventMモナドと格闘する必要があります。私はまだHaskellに十分な能力を持っていないと言わなければなりません。単純なモナドがどのように機能するかはある程度理解していますが、この1つの「typeEventM ta = ReaderT(Ptr t)IO a」(Graphics.UI.Gtk.Gdk.EventMで定義)は私には不思議に思えます。
私の質問は:誰かがEventMモナドの内部を説明してもらえますか?たとえば、「buttonPressEvent :: WidgetClass self => Signal self(EventM EButtonBool)」の場合です。