бесконечный цикл в функциональном программировании?

  • мне было интересно: можно ли бесконечные циклы делать в функциональном программировании?

пример: при использовании Windows API для получения сообщений windows он обычно реализуется в цикле.

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

  • бесконечный цикл неправильный ум-набор для функционального программирования ?

  • интерфейс операционной системы или аппаратной проблемы ?

мне не кажется, что это функциональная программа / О. s. может продолжать работать сам по себе

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

4 ответов


как и другие опубликовали, бесконечный цикл is можно через рекурсии хвоста.

Е. Г. loop() будет эффективно работать как бесконечный цикл (в постоянном пространстве стека), так как компилятор может оптимизировать хвостовой рекурсивный вызов loop В конце.

let loop() = do {
  println("foo")
  loop()
}

но

бесконечный цикл-неправильный ум для функционального программирования ?

все-таки есть смысл. Рассмотрим ваш Windows-API пример с бесконечным циклом. Это что угодно, только не функционально. Помните-функциональные средства мышления в значениячто они означают). Поэтому лучше пойти на реактивный / основанный на событиях подход, такой как [псевдо-функциональный код]

  (onClick form1)
|> Event.subscribe (\pt-> do { print $ "I was clicked at " ++ (show pt) })

так

мне не кажется, что это функциональная программа / О. s. может продолжать работать сам по себе

is технически неправильно - вы can реализуйте бесконечные циклы - но часто нет (функциональной)точки в этом. Зачем это нужно, кроме как для какого-то опроса IO? Преобразование значений чисто функциональным способом должно завершаться, чтобы быть значимым.


Если вы используете хвостовая рекурсия, у вас фактически есть итерация, например цикл for/while. Поэтому, я думаю, вы можете иметь бесконечный цикл без переполнения стека.

на ваш вопрос: "являются ли бесконечные петли неправильным умом для функционального программирования?" может это поможет: - While или хвостовая рекурсия в F#, что использовать, когда?


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

редактировать Я не хочу не соглашаться с другими ответами, но "бесконечные" хвостовые рекурсивные петли являются общей идиомой для работы с внешним миром. Следующий пример взят из Реальный Мир Haskell, и является представителем идиома.

mainloop :: Handle -> Handle -> IO ()
mainloop inh outh = 
    do ineof <- hIsEOF inh
       if ineof
           then return ()
           else do inpStr <- hGetLine inh
                   hPutStrLn outh (map toUpper inpStr)
                   mainloop inh outh

мы по существу рассматриваем внешний мир как поток.


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

подавляющее большинство кода в чисто функциональной программе должно быть написано в общем подмножестве, т. е. использовать шаблоны, такие как структурная рекурсия или корекурсия (которые обеспечивают завершение и прогресс), а не возвращаться к общей рекурсии. Надеемся, что будущие версии GHC будут включать в себя прямую поддержку обнаружения некоторого общего подмножества Haskell и выдачу предупреждений для кода, который не может быть доказан для завершения или прогресса.