Я пытаюсь определить API для выражения определенного типа процедуры в моей программе.
newtype Procedure a = { runProcedure :: ? }
Существует состояние, состоящее из сопоставления идентификаторов с записями:
type ID = Int
data Record = { ... }
type ProcedureState = Map ID Record
Существует три основных операции:
-- Declare the current procedure invalid and bail (similar to some definitions of fail for class Monad)
abort :: Procedure ()
-- Get a record from the shared state; abort if the record does not exist.
retrieve :: ID -> Procedure Record
-- Store (or overwrite) a record in the shared state.
store :: ID -> Record -> Procedure ()
У меня есть несколько целей с этими операциями:
- Процедуры могут делать предположения
(в отличие от вызова raw
Map.lookup
) о какие записи доступны, и если любые их предположения ошибочны, Процедура в целом возвращается отказ. - Ряд процедур может
соединяться цепью, используя
<|>
(от класс Альтернатива), чтобы упасть вернуться к процедурам, которые различные предположения. (Похожий на STMorElse
)
Учитывая эти цели, я считаю, что мне нужна комбинация монадов State
и Maybe
.
-- Which to choose?
type Procedure a = StateT ProcedureState Maybe a
type Procedure a = MaybeT (State ProcedureState) a
Я не могу понять, как будут вести себя два порядка Maybe
и State
. Может ли кто-нибудь объяснить разницу в поведении между двумя порядками?
Кроме того, если вы видите проблему с моим оригинальным мышлением (возможно, я слишком сложный), не стесняйтесь указать на это.
Вывод:
Все три ответа были полезны, но была одна общая идея, которая помогла мне решить, какой заказ я хотел. Посмотрев на тип возврата runMaybeT
/runStateT
, было легко увидеть, какая комбинация имела поведение, которое я искал. (В моем случае мне нужен тип возврата Maybe (ProcedureState, a)
).