169 похожих чатов

Всем привет. При изучении haskell дошел до ввода вывода и

рекурсивного вызова main. Стало интересно на счет переполнения стека из-за такой рекурсии
Нашел в интернете такой вопрос на stackoverflow:
https://stackoverflow.com/questions/9015318/what-to-use-instead-of-a-main-loop-in-haskell

И в первом ответе сказано про отсутствие проблем, так как действие будет отброшено.

Как понимать эти слова? Что именно будет отброшено? Что если внутрь do добавить что-нибудь в духе
str <- getLine
str будет иметь тип String, а не IO String, будет ли она "засорять" стек?

Или я рано задался этим вопросом и нужно сперва дойти до монад и т.п.?

19 ответов

25 просмотров

https://ru.m.wikipedia.org/wiki/%D0%A5%D0%B2%D0%BE%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D1%8F_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F

Alexey-Ismagilov Автор вопроса
Cheese Syrowiecki
https://ru.m.wikipedia.org/wiki/%D0%A5%D0%B2%D0%BE...

А как понять, когда хвостовая рекурсия есть, когда ее нету. В смысле когда компилятор это использует. Правильно ли я понимаю, что такое может быть реализовано только для функций вида (пишу не на haskell) def f(...): ... return f(...) Но не для def f(...): ... return 1 + f(...) Так как тут, по сути, f(...) используется в контексте 1+... ?

Alexey Ismagilov
А как понять, когда хвостовая рекурсия есть, когда...

для нехаскеля правильно. в Хаскеле код совсем иначе придётся

Alexey Ismagilov
А как понять, когда хвостовая рекурсия есть, когда...

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

хвостовой вызов сильно проще монад, и не требует монад

Alexey-Ismagilov Автор вопроса
Cheese Syrowiecki
хвостовой вызов сильно проще монад, и не требует м...

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

Alexey-Ismagilov Автор вопроса
Cheese Syrowiecki
обычно понять очень легко. если результат функции ...

Вот, например, найдет ли в следующем коде компилятор хвостовую рекурсию? lenImpl :: [a] -> Int -> Int lenImpl [] n = n lenImpl (x:xs) n = lenImpl xs (n+1) len :: [a] -> Int len x = lenImpl x 0 Правильно ли я понимаю, что тут все равно остается проблема ленивости вычислений и я буду иметь дело с выражением (((1+1)+1)...)?

Alexey Ismagilov
Я просто думал, что разгадка кроется, например, в ...

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

Alexey Ismagilov
Вот, например, найдет ли в следующем коде компилят...

компилятору не надо её искать. хвостовой вызов — это просто самый внешний вызов

Alexey Ismagilov
Вот, например, найдет ли в следующем коде компилят...

правильно понимаете. не стэк вызовов будет занимать память, а граф задумок

Alexey Ismagilov
Вот, например, найдет ли в следующем коде компилят...

но в данном случае легко заставить сумму вычисляться на месте

Alexey-Ismagilov Автор вопроса

Если не затруднит, не могли бы привести как реализовать данную оптимизацию. Или речь идет про bang pattern?

на самом деле не вызов, а применение. в ленивом языке есть отличие между ними

Alexey-Ismagilov Автор вопроса
Гриша Герасев
А что такое вызов тогда и в чем отличие?

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

Гриша Герасев
А что такое вызов тогда и в чем отличие?

вызов — это переход к исполнению кода функции. когда функция применяется к аргументам, сначала создаются задумки, но вычисление не происходит. когда требуется получить значение задумки, происходит вызов

Cheese Syrowiecki
вызов — это переход к исполнению кода функции. ког...

А применение функции создает задумку? Понятно.

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта