Что, если таковые имеются, не так с этим подходом к декларативному вводу-выводу



Я точно не знаю, насколько это относится к "программированию", а не к "проектированию языка программирования". Но проблема вот в чем:



Скажем, для простоты у нас есть два "специальных" списка/массивы/векторы/то, что мы просто называем "портами" для простоты, один называется stdIn, а другой stdOut. Они концептуально представляют соответственно


  • весь пользовательский ввод, заданный программе в течение срока действия программы

  • Все выходные данные, записанные на терминал в течение программа


В псевдокоде, вдохновленном Хаскеллом, должно быть возможно создать эту полностью декларативную программу:



 let stdOut =   ["please input a number", 
"and please input another number",
"The product of both numbers is: " ++ stdIn[0] * stdIn[1]]


Который сделает ожидаемое, попросит два номера и напечатает свой продукт. Фокус в том, что stdOut представляет собой список строк, записанных в терминал по завершении программы, а stdIn-список входных строк. Ошибки типа и тот факт, что должна быть некоторая гарантия, чтобы напечатать только следующую строку после того, как была создана новая строка. войдя сюда налево для простоты, это, вероятно, достаточно легко решить.



Итак, прежде чем я приступлю к реализации этой идеи, есть ли в ней какие-либо подводные камни, которые я упустил из виду? Я не знаю о существовании подобной конструкции, поэтому было бы наивно не принимать во внимание, что в ней есть очевидная ловушка, которую я упустил из виду.

В противном случае, я знаю, что конечно:



 let stdOut =   [stdIn[50],"Hello, World!"]


Было бы ошибкой, если бы эти результаты нужно было переплетать таким же образом, как и выше.
674   4  

4 ответов:

Аналогичный подход использовался в ранних версиях Haskell, за исключением того, что элементы каналов stdin и stdout были не строками, а общими "действиями" ввода-вывода-фактически, вход и выход были обобщены до "ответа" и "запроса". Пока оба канала являются ленивыми (то есть они фактически являются "итераторами" или "перечислителями"), среда выполнения может просто ходить по каналу запроса, действовать на каждый запрос и прикреплять соответствующие ответы к каналу ответа. К сожалению, эту систему было очень трудно создать. использование, так что он был слом в пользу монадической ИО. Смотрите эти документы:

  • г, п., и Sundaresh, Р. О выразительности чисто-функциональных систем ввода/вывода. Тех. REP. YALEU / DCS/RR-665, факультет компьютерных наук, Йельский университет, март. 1989 год.
  • Пейтон Джонс, С. решении отряд новобранцев: монадическом ввод/вывод, многопоточность, исключения, и на иностранных языках звонки в Haskell. В инженерных теориях построения программного обеспечения, 2002, с. 47 -- 96.

Подход, который вы описываете, звучит как " диалоги."В своей отмеченной наградами статье 1993 года императивное функциональное программирование Фил Уодлер и Саймон Пейтон Джонс приводят некоторые примеры, когда диалоги действительно не очень хорошо работают, и они объясняют, почему монадический ввод/вывод лучше.

Я не вижу, как вы будете плести их, рассматривая этот пример по сравнению с вашим собственным:

let stdOut =   ["Welcome to the program which multiplies.",
                "please input a number", 
                "and please input another number", 
                "The product of both numbers is: " ++ stdIn[0] * stdIn[1]]

Должна ли программа запрашивать число, представленное stdIn[0], после вывода одной строки (как в вашем примере) или двух строк? Если индекс 0 представляет 0-й вход из stdin, то он выглядит примерно так:

let stdOut =   ["Welcome to the program which multiplies.",
                "please input a number",
                some_annotation(stdIn[0]),
                "and please input another number", 
                some_annotation(stdIn[1]),
                "The product of both numbers is: " ++ stdIn[0] * stdIn[1]]

Потребуется для того, чтобы скоординировать сроки вывода и ввода.

Мне нравится ваша идея. Замените some_annotation на ваши предпочтения, возможно, что-то сродни " синхронизировать?- Я не смог подобрать для этого острого слова.

Этот подход, по-видимому, является "наиболее очевидным" способом добавления ввода-вывода к чистому λ-исчислению, и другие люди упоминали, что нечто подобное было опробовано в Хаскелле и Миранде.

Однако я знаю язык, не основанный на λ-исчислении, который все еще использует очень похожую систему:

Как обрабатывать входные и выходные данные в a язык без побочных эффектов? В определенный смысл, вход и выход не являются побочные эффекты; они, так сказать, фронт и обратные эффекты. (...) [Программа есть] функция из космоса возможных входов в пространство возможные выходы.

Входные и выходные потоки являются представлены в виде списков природных числа от 0 до 255, каждое соответствует одному байту. Конец файла представляется значением 256, не к концу списка. (Это потому, что это так часто проще иметь дело с EOF в качестве характер, чем как частный случай. Тем не менее, я задаюсь вопросом, если бы это было не так лучше использовать конец списка.)

(...)

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

(...) Самый очевидный способ письма эта конкретная программа-К минусам вместе "Привет, [имя]!" строка в выражении который обусловлен при получении новой строки. Если вы это сделаете это вы в безопасности, потому что там нет способ для любого оценщика доказать в заранее, что пользователь когда-либо наберет a новая строка.

(...)

Таким образом, нет никакой практической проблемы с интерактивное программное обеспечение. Тем не менее, в этом есть что-то неприятное. таким образом предотвращается второй случай. Один совершенно прозрачна программы не стоит полагаться на лентяев оценка для того, чтобы правильно работать.

Как избежать этой моральной дилеммы? То трудный путь состоит в том, чтобы переключиться на более возможно, сложная система ввода-вывода основанный на Хаскелле, в котором входной сигнал и выходные данные явно синхронизированы. Я довольно не склонен делать это, так как Я гораздо больше предпочитаю простоту существующая система. Самый простой выход-это писать пакетные программы, которые случаются с хорошо работайте в интерактивном режиме. Это главным образом, просто вопрос не побуждения пользователь.

Возможно, Вам понравится делать некоторые программирование в Lazy K ?

Comments

    Ничего не найдено.