Реализация >>= в новом типе

Позвольте мне начать с задачи, которую я хочу решить, возможно, я иду не в ту сторону. Я использую Snap Framework для игрушечного проекта, и главное, что он работает под Snap монада. Мне нужно добавить свое состояние над ним. Я использую монадный трансформатор:

type SnapApp a = StateT AppState Snap a

Это определено в модуле, скажем, Base, Так как он мне нужен в других модулях, я должен его экспортировать:

module Base
  ( ..
  , SnapApp
  ) where

Это хорошо, но я хочу, чтобы этот модуль не экспортировался SnapApp является монадой состояния, потому что у меня есть сложная обработка для установки некоторых атрибутов для состояния. Например, сессия. Я должен написать файл, когда он будет изменен, поэтому неправильно просто get и тогда put модифицированный сеанс, должна быть вызвана специальная функция. Итак, я скрываю, что с помощью newtype а не экспортер данных констестор:

newtype SnapApp a = SnapApp (StateT AppState Snap a)

Я сделал это экземпляром моего класса с функциями для изменения сессии и т. Д. Но возникает проблема: я потерял экземпляры Monad класс и прочее для новых SnapApp, И я застрял с реализацией >>=:

instance Monad SnapApp where
    return = SnapApp . return
    mx >>= fm = -- HOW?

Спасибо!

2 ответа

Решение

Пусть типы направляют вас. Тебе нужно

(>>=) :: SnapApp a -> (a -> SnapApp b) -> SnapApp b

У тебя есть

(>>=) :: StateT AppState Snap a -> (a -> StateT AppState Snap b) -> StateT AppState Snap b

Вам необходимо конвертировать:

  • аргумент SnapApp a в StateT AppState Snap a
  • аргумент a -> SnapApp b в a -> StateT AppState Snap b
  • результат StateT AppState Snap b в SnapApp b

1) использовать сопоставление с образцом; определить:

fromSnapApp (SnapApp x) = x

2) Составьте функции a -> SnapApp b а также SnapApp b -> StateT AppState b

3) Использование SnapApp

Конечный результат:

x >>= f = SnapApp (fromSnapApp x >>= (fromSnapApp . f)) 

или же:

SnapApp x >>= f = SnapApp (x >>= (fromSnapApp . f)) 

Вам не нужно писать это; GHC может получить экземпляр, если вы включите GeneralizedNewtypeDeriving расширение:

newtype SnapApp a = SnapApp (StateT AppState Snap a) deriving (Monad)

Это управление состоянием - именно то, что мы разработали для вас. Наша монада Handler на самом деле является просто оболочкой нового типа StateT s Snap с несколькими дополнительными вещами, встроенными для удобства. Мы раскрываем экземпляр MonadState, чего вы пытаетесь избежать, но вы можете справиться с этим, инкапсулировав тип вашего состояния в модуль и не экспортируя для него никакие методы доступа. Вы можете экспортировать только нужные функции-обработчики, которые выполняют всю сложную обработку атрибутов.

Другие вопросы по тегам