У меня есть тип состояния с операторами >>
и >>=
, который почти является монадой. Предполагаемое использование - генерировать код для другого языка, а доступность do-notation будет очень уместной.
Тем не менее, нет четко определенной функции возврата, так как значения должны только создаваться вместе с побочными эффектами. Итак, если я подделываю функцию возврата, возвращаемая функция должна возвращать только ошибку, и она нарушает законы монады. (I.e. никогда не действует для использования функции возврата.)
Что я наблюдаю, так это то, что do-notation только сахарирует два оператора, операторы >>
и >>=
.
Есть ли способ сохранить что-то вроде обозначений для этих двух операторов или что-то такое же чистое, но без создания монады?
ПРИМЕЧАНИЕ. Ниже строки указаны детали, которые не нужны для вопроса в заголовке. Это контекст для того, почему я задал вопрос, ответы на которые мне интересны. Другие, которые просматривают эту тему, вероятно, предпочли бы игнорировать ее.
КОРРЕКЦИЯ: Я не создаю код на императивном языке, хотя это не имеет значения. Я генерирую код в Javascript.
CLARIFICATION (в ответ на bdonlan): My type is (ma), который несет состояние (это код, который будет сгенерирован с учетом различных параметров, аналогичный государственной монаде) и вернет значение (имена переменных в сгенерированный код с прикрепленным типом haskell). Таким образом, не должно быть способа вернуть значения, которые связаны с именами переменных, без генерации кода, который определяет имена переменных. * Это исключительно из-за моего дизайна, который может быть хуже других, о которых я не думал.
В ответ на ответы: Кажется, есть два вида ответов на это. Во-первых, действительно ли это возможно и, возможно, лучший способ использовать обозначение do. Второй вопрос о том, лучше ли использовать монаду и определить возврат (или даже имеет смысл не делать этого - возможно, в более поздний момент времени, я бы нашел, что требуется возврат).
Пример того, что я буду делать:
data JsState = JsState { code :: String , vidCount :: Int }
-- vidCount is for generating unique variable names
newtype JsStmt = JsStmt ( JsState -> JsState )
newtype JsMonad a = JsMonad ( JsState -> ( a , JsState ) )
def :: (JsValue a) => a -> JsMonad a
-- Outputs "var " ++ toUniqueVarName vidCount ++ " = " toCode a ++ ";"
-- Returns JsMonad with the variable name as the value,
-- with a type attached, and the JsState vidCount is incremented by 1.
alertJsInt :: JsIntE -> JsMonad ()
-- Outputs something like "alert(" ++ toCode JsIntE ++ ");"
do
x <- def $ JsIntL 2
y <- def $ JsIntL 4
alertJsInt (x + y)