Я пытаюсь реализовать небольшое настольное приложение, используя HDBC
и Haskell.GI
. Я строю свои окна и диалоги, используя glade, и загружаю их с GtkBuilder
. После реализации нескольких сценариев я в конечном итоге использовал один и тот же шаблон, составляя «действия» в do
блоках с сигнатурой:
Connection -> Builder -> a -> IO b
Эти "действия" сочиняются в контексте монады IO
, главная проблема в том, что мне приходится передавать свои Connection
и Builder
вокруг. Еще одна проблема, которую я предвижу, заключается в том, что если я захочу добавить еще одну внешнюю зависимость к своему приложению (например, доступ к сканеру изображений), мне придется изменить сигнатуру всех моих «действий» и, что более важно, их арность.
Что я мог сделать: я мог определить синоним типа:
type Action a b = Connection -> Builder -> a -> IO b
Я также мог бы создать именованный кортеж для устранения проблемы арности:
data Context =
Context {
conn :: Connection,
builder :: Builder}
Но, тем не менее, это не решает тот факт, что каждый раз, когда я хочу получить доступ к базе данных, мне придется вызывать (conn ctx)
или использовать привязку let
в каждом действии.
То, что я чувствую, было бы идеально, если бы я создал свою собственную монаду, в которой я мог бы составлять свои действия, и я бы не говорил явно о своих Connection
или Builder
значениях.
Как бы мне определить такое монаду, зная, что IO
уже является монадой?
Кстати, это как-то связано с State
монадой?