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 ответов

9 просмотров

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
вызов — это переход к исполнению кода функции. ког...

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

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

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

Такой вопросец - есть функция function MySuperDuperConcat(const a: array of AnsiString): AnsiString; Как мне в её теле сделать вот так? Result:=Concat(a); А не грустный вариан...
notme
15
Есть какой-нибудь для Delphi/FPC T*Compression(Decompression)Stream на базе LZ4/Zstd/любой другой быстрый(и хорошо сжимающий) алгоритм А ещё лучше в pure pascal А ещё лучше од...
notme
48
type TObj = object procedure Init; virtual; end; TObj1 = object(TObj) procedure Init; override; end; procedure TObj1.Init; begin inherited; end; procedur...
Alexander 👋
29
А чем вам питонисты не угодили?😂
.
79
Вот смотрите у меня есть два стрима сейчас fs, cs: TStream; fs := TFileStream.Create('filename'); cs := TCompressionStream.Create(compression_level, fs); Я хочу сделать так: ...
notme
5
Всем привет, написал код ниже, но он выдает сегфолт, в чем причина? #include <stdio.h> #include <stdlib.h> #include <string.h> struct product { char *name; float price; };...
buzz базз
83
Можно ли загрузить скрипт py в бота чтобы он работал по нему? как это сделать?
huskadam #RCC Фанат? @hitlerpvp
13
Всем здравствуйте! Я хотел узнать сколько стоит средняя месячная зарплата у Electron js разработчиков? Мне очень это важно и нужно, плиз помогите узнать эту инфу! Для Джунио...
U.K.
10
Hello. Could you please help me with finding all coordinates within a radius using a spatial index, given that I have a table with coordinates? SET @lng = 37.57925; SET @lat ...
Rinchin G
8
free(NULL) это UB?
#
8
Карта сайта