LINUX.ORG.RU

Как в Хаскеле сделать try..catch..finally?

 ,


0

1

Как написать вот это:

зайти-в-сарай()
try
  ткнуть-палкой-в-осиное-гнездо-в-сарае()
catch all
  вернуть "Ой"
end

и вот это:

зайти-в-сарай()
try
  ткнуть-палкой-в-осиное-гнездо-в-сарае()
finally
  уходя-из-сарая-погасить-свет()
end

И вообще, есть ли где-нибудь гайд по хаскелю для тех, кто приходит с других языков, который бы не начинался со слов «оставь своё эго за порогом, когда приходишь в мир хаскеля».

★★★★★

Последнее исправление: den73 (всего исправлений: 5)

Я так понял, что maybe - это способ сказать «ой, ничего не получилось»

Нет. Обычно, это способ сказать «ура, что-то есть» и «ничего нет».

Вот это и есть Maybe

Это Either. В твоём случае Either () String.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

поправил, и заодно код поправил.

den73 ★★★★★
() автор топика

Посмотри как реализовали обработку ошибок в расте через алгебраический тип данных Result<Ok,Fail>. С макросами он внешне весьма похож на try-catch и применяется в подобных ситуациях, хоть и внутри на try-catch ни разу не похож. Кроме того он более близок к императивному стилю чем хасклевские структуры.

Но если хочешь, то говоря твоим языком можно сделать так:

ткнуть_в_гнездо      :: (Either ЧтоЖеМожетПойтиНеТак ())
посмотреть_на_гнездо :: (Either ЧтоЖеМожетПойтиНеТак ())

instance Monad (Either ЧтоЖеМожетПойтиНеТак) where
    return a = Right a
    a >>= b =
        case a of
            Left x  -> Left x
            Right x -> b x

вечер_в_сарае = do
    посмотреть_на_гнездо
    ткнуть_в_гнездо
    ткнуть_в_гнездо
    return уходя_из_сарая_погасить_свет
    

Aswed ★★★★★
()

Аналог для чего? В чем вопрос?

Finally и есть finally. В haskell даже такая одноименная функция есть в разных монадах. В чистом коде finally быть не может по определению (ссылочная прозрачность, все дела - откуда мы знаем, где когда какое значение было раскрыто в более простую форму)

dave ★★★★★
()

сарай
ткнуть
ой

Зачем ты смешал вселенную FO:E со вселенной SHED.MOV?

bodqhrohro_promo
()
Ответ на: комментарий от Aswed
вечер_в_сарае = do
   let результат = действия
   уходя_погасить_свет
   return результат
 where
   действия = do
     посмотреть_на_гнездо
     ткнуть_в_гнездо
     ткнуть_в_гнездо

же?

qnikst ★★★★★
()

нет, ты совсем начего не понял, я даже не знаю с какой стороны сказать что тут не так, т.к. не так вообще все..

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Возможно. Сейчас переформулирую вопрос.

den73 ★★★★★
() автор топика
Ответ на: комментарий от qnikst

И вот я точно не понял, почему в гнездо нужно ткнуть два раза. Это опечатка или я попал в Кафку?

den73 ★★★★★
() автор топика

Ты хочешь, чтобы тебе плохо и малопонятно вкратце пересказали главу из учебника по хаскелю про монаду Maybe? Ничего хорошего не выйдет, лучше обратиться к первоисточнику, заодно подтянешь недостающую теор. базу, что такое монады вообще.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

И желательно без теорката и эндофункторов. Я нашёл счастье (т.е. определение монады) в википедии. Вот в таком же стиле, без зауми, хочу понять и всё остальное. За последние дни нашёл несколько постов на хабре и пр, из которых окольными путями становится что-то ясно, но целостной картинки пока нет. Ещё очень не мешал бы гайд по приоритету выражений в Хаскеле, иначе я просто не могу распарсить, в т.ч. и вышеприведённый код.

den73 ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

Насчёт maybe А должно быть написано, что это «составной тип, выражающий либо тип А, либо некую пустоту». Вот either пока да, не понял. do - это видимо, ситуация, когда если встречается команда «ткнуть-в-осиное-гнездо», то последующие вычисления могут принять неконтролируемый характер.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Насчёт maybe А должно быть написано, что это «составной тип, выражающий либо тип А, либо некую пустоту».

примерно так, да

do

Это так называемая «do-нотация». Которая является сахарком. Но этот сахарок раскрывается в такую муть, что тебе поплохеет, если захочешь в нее вот так сразу с кондачка вникнуть.

Мое мнение таково, что сложные вещи должы быть сложными для понимания. Тогда, сломав моск, выйдешь на новый уровень понимания. Если же сделать более доступным для понимания, то неизбежно придется упрощать, что не есть хорошо. А объяснить сложное простыми словами могут единицы, это не так просто.

Virtuos86 ★★★★★
()
Ответ на: комментарий от den73

но целостной картинки пока нет

Ее нет, потому что ты пытаешься идти окольной дорогой. А прямая дорога лежит здесь:

теорката и эндофункторов

Virtuos86 ★★★★★
()
Ответ на: комментарий от den73

О Хаскел по человечески, Денис Шевченко?

den73 ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

Ну да, да, процедура иницииации. Насрать человеку на голову всей казармой - тогда он станет настоящим солдатом.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

И ещё: «верую, потому что абсурдно». Чистый функциональный язык, но не чистый. Война - это мир. Я не хочу ломать свой мозг. Я лучше либо как-нибудь доживу без Хаскеля, либо разберусь в нём своим способом.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Нет. Люди не просто так пишут учебники. Почему некоторые считаются отличными, а другие отстойными? Нужен особый талант, и владение материалом. А ты хочешь, чтобы тебе на форуме кто-то рассказал и объяснил кусок лямбда исчисления наглядно и просто. Да фиг у кого получится, только тебе голову запудрят.

Полистай хоть «Изучай Haskell во имя добра» Липовача, у нее репутация дружелюбной к новичкам. Сам я, кстати, хаскель не осилил, поэтому не воспринимай как снобизм написанное выше.

Virtuos86 ★★★★★
()
Ответ на: комментарий от den73

почему бы и нет, если исключение не вылезло

qnikst ★★★★★
()
Ответ на: комментарий от Virtuos86

это?

@article{Moggi89,
author = {Moggi, Eugenio},
doi = {10.1109/LICS.1989.39155},
isbn = {0-8186-1954-6},
journal = {Proceedings. Fourth Annual Symposium on Logic in Computer Science},
keywords = {haskell,monads,theory},
pages = {14--23},
publisher = {IEEE Comput. Soc. Press},
title = {{Computational lambda-calculus and monads}},
url = {http://ieeexplore.ieee.org/lpdocs/epic03/wrapper.htm?arnumber=39155},
year = {1989}
}

а оверкилом не будет?

qnikst ★★★★★
()
Ответ на: комментарий от den73

do это сахар для

do { a ; b} ----> a >> b
do { let a = x ; b  } -----> let a = x in b
do { return x }       -----> return x
do { a ; b ; c }      -----> a >> (b >> c)

either A B; или значение A или значение B.

поведение зависит от реализации bind (>>=) в Monad, например, для Maybe:

Nothing >>= _ = Nothing
Just x  >>= f = f x

для Either:

Left x >>= _ = Left x
Right x >>= f = f x
qnikst ★★★★★
()
Ответ на: комментарий от qnikst

do это сахар для

Во, отлично. Спасибо! Близко к теме. ПРавда, я не всё распарсил, но надеюсь, что завтра осилю.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Ну раз ты не осилил, возможно твой путь ведёт в тупик. А «о хаскел по человечески» ты смотрел? Он есть в сети в pdf.

den73 ★★★★★
() автор топика
Ответ на: комментарий от qnikst

Шарик, ты балбес. Если прочитать внимательно мой комментарий (Как в Хаскеле сделать try..catch..finally? (комментарий)), то станет ясно, что под «оригиналом» я подразумевал учебную информацию, по которой условные советчики осваивали Хаскелл. Если для тебя это была и та научная статья, которую ты упомянул, то для тебя это действительно оригинальный источник. Но зачем обобщать на всех свой личный опыт?

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

ты меня обратно не заигнорил ещё? Если нет, то большинство изучавших минимум читали RWH, LYAH, Gentle introduction into haskell (но люди заставшие эту книгу наверное умерли от старости) и 100500 монадных туториалов один другого хуже, поэтому объяснения строятся на какой-то суперпозиции данных источников, и что такое первоисточник становится совсем не понятно.

qnikst ★★★★★
()
Ответ на: комментарий от den73

Поскольку ты всё-таки наступаешь на грабли, о которых я тебя предупреждал (вон и популяризатор сыскался, осведомленный аж о самой оригинальной теоретической работе), я, наверное, сваливаю.

Virtuos86 ★★★★★
()
Ответ на: комментарий от den73

Если только вторую версию, при написании первой, к сожалению Денис ещё не знал Haskell. Сейчас любят рекомендовать Haskell from the first principles, если нравится прорываться через тонны воды, то покатит.

Вот достаточно новая подборка, по ней есть ссылки на более подробные рецензии https://medium.com/@_bravit/книги-по-программированию-на-haskell-выводы-712c1...

qnikst ★★★★★
()
Ответ на: комментарий от Virtuos86

не, мне лень нести людям свет, есть вопросы - я отвечаю, рассказывать с нуля и правильно, мне лень и нет смысла, да и все равно не лучшим образом сформулирую.

Популяризаторством занимаются те, у кого язык подвешен хорошо, а я тихо и мирно починяю примусы на haskell и изредко заглядываю на лор.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

ты меня обратно не заигнорил ещё?

Когда пол-треда скрыто, приходится читать всё подряд.

суперпозиции

This. Но ТС ты эту суперпозицию не перескажешь, потому как придётся начать писать свой учебник хаскеля в комментариях. Причём плохой, потому что наспех и второпях.

Virtuos86 ★★★★★
()

Еслихаскель функциональный, то там должно быть что-то вроде

1/1.0
ой, типы не совпадают
огребай(размер операндов) {
}
огребай(знак операндов) {
}
огребай(внутренняя ошибка) {
}
огребай(выход) {
}

anonymous
()
Ответ на: комментарий от Virtuos86

Когда пол-треда скрыто, приходится читать всё подряд.

:[

This. Но ТС ты эту суперпозицию не перескажешь, потому как придётся начать писать свой учебник хаскеля в комментариях. Причём плохой, потому что наспех и второпях.

Ну как я в своём первом коментарии ТС сказал, что в сообщении (не исправленом) было все настолько плохо, что неясно, что сказать. Если бы был конекретный вопрос или частично правильное восприятие то можно было бы дополнить. И ты прав, что лучше начать с какого-нибудь учебника.

Ладно извини, я действительно пытался сострить про «оригинал».

ТС, если не лень потратить 10-15 минут, и совсем базовый ТК не пугает, то в той статье вполне можно прочитать вступление и первые пару глав, чтобы понимать откуда ноги растут. Учебник это правда не заменит.

qnikst ★★★★★
()

да, про изначальный вопрос, если с учетом асинхронных исключений или IO то тогда делается через:

Control.Exception.catch :: Exception e => (IO a) -> (e -> IO a) -> IO a
Control.Exception.finally :: IO a -> IO b -> IO a

если чистое, то или через ExceptT или напрямую.

qnikst ★★★★★
()

Добавлю еще, чтобы совсем стало непонятно)

В Haskell catch и finally - функции. В своем простейшем виде они очень похожи на одноименные конструкции из каких-нибудь Java или Си++, потому что с некоторой натянутостью можно считать, что все вычисления, что происходят в Java и Си++, происходят в монаде IO.

Но любой желающий может написать свою монаду. Если она императивная, т.е. основана на IO, то для нее тоже желательно определить свои обработчики catch и finally. И вот здесь начинается самое интересное.

Например, если взять продолжения, «матерь всех монад», то нужно взять, как минимум, два продолжения (а лучше три) и их можно обернуть в одно вычисление. Тогда для них тоже можно определить catch и finally. Сами определения не такие чтобы сложные, всего на десяток строк каждое, но я думаю, что далеко не каждый в них разберется.

Если haskell покажется сложным, то можно посмотреть, как это сделано в F# из .NET. Там есть так называемые «computation expressions». Есть формулы, как раскрываются try-finally и try-with (catch) - это оно самое. Есть монада Async для асинхронных вычислений. Можно там глянуть на то, как реализуются catch и finally. И тогда можно будет вернуться снова к haskell.

А, вообще, finally часто реализуется по рабоче-крестьянски через catch, где считается, что любое прерывание вычисления должно происходить через бросание исключения (синхронного и асинхронного). Это распространенный способ реализации finally в haskell, но это не значит, что он самый правильный. По идее отменить вычисление можно и без кидания исключениями

dave ★★★★★
()
Ответ на: комментарий от qnikst

Exception

Нет. Меня интересуют инструменты для работы с императивным кодом. Например, cps преобразование. Инструментирование для отладки. Частичное применение. И прочая. Видимо, монады Хаскеля - это один из вариантов такого инструмента. Вот я и выясняю, насколько они применимы (удобны) для моделирования и анализа «обычного» императивного кода. Не только с исключениями, но и с обработчиками сигналов. Т.е. мне нужно не бросить исключение, а рассуждать о коде, бросающем исключение.

den73 ★★★★★
() автор топика
Ответ на: комментарий от dave

для нее тоже желательно определить свои обработчики catch и finally.

Отлично. Есть ли где-нибудь уже определённая библиотечка на хаскеле для моделирования потока вычисления какого-нибудь «недоси++» с if,for, обработкой сигналов и исключениями?

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

if,for

Это и из коробки есть в общем-то

обработкой сигналов и исключениями

Вот тут закончится чистота и начнётся IO, чего в хаскеле обычно стараются избегать

Softwayer ★★
()
Ответ на: комментарий от Softwayer

Это личный выбор избегающих, а меня интересует, как работать с таким кодом. Притом, заметь, сам процесс инструментирования кода можно считать чистым. Только лишь процесс его исполнения чистым не является.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Не совсем понял вопроса. Как заметили выше, для if и for все уже есть, применимое ко всем монадам.

Что ты имеешь в виду об обработкой сигналов и исключений?

Про то, что в haskell пытаются избежать императивного кода - неправда или, как минимум, полуправда. Задачи у всех разные. В учебниках по haskell иногда перегибают палку на мой взгляд, и бывает, что очень сильно. Не буду цитировать один русскоязычный учебник, но там такая муть была написана (возможно, потом переписали).

В монаде IO довольно много разных комбинаторов, в том числе, например, для временного экранирования от сигналов операционной системы и прочие вещи.

Ну, и в haskell, в отличие от подавляющего большинства известных языков исключения еще могут быть асинхронными. Благодаря поддержке рантайма языка можно из одного потока бросить исключение в другой уже исполняющийся поток

dave ★★★★★
()
Ответ на: комментарий от dave

Не совсем понял вопроса.

Ну вот для if и for есть, а для catch и throw? Ну и мне пока не совсем ясно, что есть «всё». Практическая задача, которая у меня возникала при работе в Firebird и в 1С - тотальная трассировка. Т.е., «между каждыми двумя шагами вычисления в заданной процедуре вставить некий отладочный код». Я так понял, что если в моём языке есть только if и for, то монады с этим справятся. А если есть throw и signal? Пусть пока без асинхронных исключений.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

С catch не все так просто. Даже если ты сведешь свою монаду к другой, основанной на продолжениях, то тогда можно записать что-то такое, приближенное к общему случаю, чтобы для всех и сразу, но это будет чудовищно неэффективно. Неразумно так делать. Чисто технически много лучше catch определять для каждого случая отдельно. Поэтому, видимо, и нет общего универсального комбинатора из сугубо практических соображений.

Кстати, для монады Cont нотация do и есть по-сути «автоматическое преобразование cps», о котором ты спрашивал выше

dave ★★★★★
()
Ответ на: комментарий от dave

ЧТо значит «для каждого случая отдельно»? Для каждого случая применения или для некоторого ряда применений сгодится одна?

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

из вопроса это не как не следует, монады это средство для контроля за эффектами в ленивом языке и средство для обобщения кода (одни и те же комбинаторы работающие над разными типами вычислений). И.е. это средство изнутри языка.

Если вопрос можно ли использовать монады для изучения и предбразований кода на другом языке, то прям в таком виде я сомневаюсь, код ни использует монадические методы, и маловероятно, что законы выполняются. С другой стороны, если структуры данных возникающие при анализе кода образуют монадические стукруры то это можно использовать.

Вообще я не до конца понимаю суть вопросов и боюсь, что как обычно о монадах думают как о чем-то магическом желающем жизнь счастливой.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Вообще я не до конца понимаю суть вопросов и боюсь, что как обычно о монадах думают как о чем-то магическом желающем жизнь счастливой.

Ага. Видимо, название действует магически

dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.