OberonCore
https://forum.oberoncore.ru/

Монада AND THEN
https://forum.oberoncore.ru/viewtopic.php?f=72&t=3177
Страница 1 из 1

Автор:  Geniepro [ Среда, 19 Январь, 2011 15:06 ]
Заголовок сообщения:  Монада AND THEN

Навеяно темой "Конструкция AND THEN?".
Илья Ермаков писал(а):
В ряде задач нужно ещё различать, на каком этапе неуспех. Но это делается явной переменной, хранящей текущий этап.
Код:
step := 1;
Первый_этап;
IF первый этап удался THEN
  step := 2;
  Второй этап;
AND второй этап удался THEN
  ...
ELSE
  Log.String("Ошибка на этапе "); Log.Int(step)
END

По аналогии с монадой Maybe делаем новый тип данных и прикручиваем к нему монаду:
Код:
data AndThen a = AndThen Int (Maybe a)

instance Monad AndThen where
    return a                   = AndThen 0 (Just a)
    fail _                     = AndThen 0 Nothing
    (AndThen x Nothing)  >>= _ = AndThen x Nothing
    (AndThen x (Just y)) >>= f = f y

calcAndThen x done failed =
    case x of
        AndThen _    (Just a) -> done   a
        AndThen step  Nothing -> failed step

Выполняемые (вычисляемые) шаги оформляются как "AndThen номер_шага вычисление". Вычисление должно выдать "Nothing" в случае неуспеха или "Just значение" в случае успеха.
Функция calcAndThen вычисляет цепочку шагов, помещённых в блок do, в случае успеха всех шагов вычисляет над результатом функцию done, в случае неуспеха -- вычисляет ф-цию failed над шагом, в котором произошёл сбой.

Тест:
Код:
main = do
    calcAndThen
        (do a <- AndThen 1 (Just 10)
            b <- AndThen 2 (Just 20)
            c <- AndThen 3 (Just 30)
            return $ a + b + c
        )
        (\x -> putStrLn $ "Result = " ++ show x)
        (\y -> putStrLn $ "Error on step " ++ show y)
Здесь все шаги успешны и результат:
Код:
Result = 60

А здесь в одном из шагов (во втором) -- сбой:
Код:
main = do
    calcAndThen
        (do a <- AndThen 1 (Just 10)
            b <- AndThen 2  Nothing
            c <- AndThen 3 (Just 30)
            return $ a + b + c
        )
        (\x -> putStrLn $ "Result = " ++ show x)
        (\y -> putStrLn $ "Error on step " ++ show y)
и результат:
Код:
Error on step 2

Не хватает синтаксического сахара, поэтому не очень наглядно. Надо подумать ещё.

Автор:  Alexey Veselovsky [ Среда, 19 Январь, 2011 15:34 ]
Заголовок сообщения:  Re: Монада AND THEN

По моему, получилось почти 1 в 1 вот это: http://www.haskell.org/haskellwiki/Exception
:-)
Да и в первой задаче вроде как не нужно было определять на каком шаге у нас всё отвалилось.

Автор:  Geniepro [ Среда, 19 Январь, 2011 18:36 ]
Заголовок сообщения:  Re: Монада AND THEN

Alexey Veselovsky писал(а):
По моему, получилось почти 1 в 1 вот это: http://www.haskell.org/haskellwiki/Exception :-)
Не могу согласиться с "почти 1 в 1" -- всё-таки протаскивания номера шага там нет. Там по сути вариация на тему монады Maybe, точнее -- это монада Either.
Alexey Veselovsky писал(а):
Да и в первой задаче вроде как не нужно было определять на каком шаге у нас всё отвалилось.
Если бы не было нужды определять шаг сбоя, можно было бы обойтись просто монадой Maybe.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/