Pull to refresh
6
@go-prolog read⁠-⁠only

User

Send message

Любопытно, а как Эвклид представлял переменные и поток команд в своем алгоритме.

Может не переменные, а парметры/неизвестные:

gcd(A,A)->A;
gcd(A,B)when A>B ->gcd(A-B,B);
gcd(A,B)->gcd(B,A).

Ого, это было обсуждение формы записи программ, а такой вопрос из сферы вычислительной сложности… Я не припоминаю средств, может профилирование, для определения "оптимальности" вычислений функции…

Попробую пояснить, это же демонстрация "ленивости" строка "inpStr <- hGetContents inh" показала, что inpStr это не сами данные, а механизм/"функция обратного вызова"/поток, который предоставит порции данных потом...

Спасибо, попробую пояснить рассуждения. Функциональное программирование, введенное Маккарти в работе над Лиспом, основано на лямбда-исчислении Черча, абстракции на которой можно строить математическую базу вычислимости как комбинации функций.
Теория категорий занимает место у основ математики, ей можно выражать и вычислимость и лямбда-исчисление, видимо, и логику предикатов — ее мощные абстракции, позволяют складывать программы от типов и описаний зависимостей между ними. Это не комбинирование функций, тут конструирование из особых функциональных объектов, которые можно вычислять, это же не чистота функций, это отсутствие средства конструировать такие объекты. Хаскел называть императивным не начинают, а механизмы линзирования встроили.


И, да, это только "название", это путаница из-за отнесения конструкций из объектов к функциональной парадигме, почему такой стиль не может иметь отдельного термина?


Бэкус из текущей истории, в упомянутой своей статье, размышляет и о Лиспе, и о его чистоте, а еще классифицирует несколько "стилей" функционального программирования: комбинации функций без использования переменных, алгебраическое ФП как у Черча, какие-то формальные ФП и "applicative state transition systems"…


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

Теорию множеств не используют при обучении арифметики или геометрии, а сейчас теория категории стала базой и для множеств, как же так? Почему Хаскелу не стать машинным языком, лисп-процессоры уже бывали)))

Однако они, тем не менее, вводятся — для удобства. Чтобы в их терминах структурировать код программы.

… и в 70-х по структурному программированию, предлагалось соблюдать модулям метрику, требование высокая связность, и такой пример называют логическая связность (это Паскалем/Ада/Модула, по памяти))):


module math;
interface:
var: state:.....
function eps():type;
function pi():type;
declaration:
var X....
.

https://ru.wikipedia.org/wiki/Связность_(программирование)


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

Все же, никакие классы, не устранят проблемы группировки функций в модуль, той самой высокой цельности модулей, вот так писать можно(С++/Ява ))):


public class programm{
  ... state;
  public: 
  void draw(io.screen);  
  sometype load_from_http(string);
}

А факты про main(IO) из Хаскел, очень подходят к определению "низкое сцепление" модулей, а именно один ее положительный вид: "сцепление по данным":


Тип зацепления, при котором выходные данные одного программного модуля служат входными данными другого модуля.

такие абстракции Хаскела не странны, это соображения из структурного подхода, а "точку входа" в программу настроит и установит окружение/операционная_система/интерпретатор.
Еще в С было, функция printf() использует файл con для вывода, а его можно передавать в программу (чем не ИО):


program >output.txt

Помню, забавная идея из языка CLIPS https://en.wikipedia.org/wiki/CLIPS, и это называли продукционным подходом к вычислениям(и сейчас существуют языки CHR), там правило выполнялось(файер), когда глобальное состояние фактов совпадет с указанным предусловием, а после выполнения правила и изменения глобального состояния будет файер у другого правила… А начинают с единого первого факта (initial-state), плюс синтаксис там лисп-овский. Порядок обхода правил, настраивался снаружи, это опция интерпретатора, текст программы этого не учитывает, система переберет правила "вширину", "вглубину", "приоритетно" или еще как, это не формулировки решаемой задачи, это механизмы "решателя" формулировок. Вот так будет машина Тьюринга:


(defrule step0 (state 0)=>
  (retract (state 0) 
  (some code)
  (assert (state 1))
)
(defrule step1 (state 1)=>
  (retract (state 1) 
  (other code)
  (assert (state 2))
)
.....
(defrule main (initial-fact)=>(assert (state 0)))

Мне как раз показалось, что обсуждения в статье "Почему функциональное программирование такое сложное" и отражают, что основы Хаскел не сколько функциональность, а только детали теории категорий, которая пугающе все абстрагировала…
Лисповская однородность представления позволяла генерировать программу, а потом ее выполнять, чем не ленивость или отложенность выполненя, в список собранные символы запустятся на самом верхнем уровне, пусть так:


(defun main (x y)
  (cons + (list x y))
)
(prog 
   (eval (main 1 2))
) 

О, если сложностью называть количество исходных абстракций, то надо сосчитать где их меньше…
Не проверил, но популярность Common лиспа точно все еще высока, поэтому и вспоминаю про него, раз тут возникает Фортран, да, ладно…
Преимущества Хаскел не могу отрицать, выражаю только недовольство его "ярлыком", странное ощущение складывается, а не какой-то ли тут план, не направленное ли переиначивание взглядов…
Доступный Эрланг без Фейсбука растерял популярность, чем плохо на нем демонстрировать подходы? Ага, это все про модность.

Ой, спасибо, интересная параллель получилась, объекты: монады ))
Объектам как структурам данных нормально быть в императивном, это же развитие Вирта — "Алгоритмы+Структуры данных=....".
Да и Питон демонстрирует функциональные элементы, по-моему, нормально, а вот с классами там странности...

Только про ясность, про восприятие, если язык следует Тьюрингу, то в нем инструкции и лента память, а если Черчу, то композиция функций, рекурсия…
Повторяюсь, наблюдаю за новостями и удивляюсь, как-то часто Хаскел фигурирует как "функциональный", а не "статически типизированный ленивый функциональный язык". В статье https://habr.com/ru/post/505928/ вижу это:


… Лямбда исчисление имеет к ФП такое отношение, как Теория Категорий, т.е. никакое. Просто люди, привнесшие эту концепцию в ФП, были прожжёнными математиками, и дали ей такое название.

это статья "Почему функциональное программирование такое сложное"…


И автор этой заметки не упоминает о старейшем языке, который ровня Фортрану, а зачем то, рядом с функциональный указывает Хаскел… и монады во втором предложении!?.. о-о-о простите за резкость…

Лисп ровесник Фортрана, но суть у них разная, Фортран — машина Тьюринга, с инструкциями и данными на бесконечной ленте, а Лисп использует абстракции Черча, на которых он желал построить основы всего математики. Лисп демонстрирует принцип "единства представления" — вычисления и данные имеют одинаковую форму записи: символы и списки.
Ленивость — о том, что функции могут не "вычислять" возвращаемый результат, а возвращать функцию, которая "потом вычислит" результат. Такое и в современном С++ можно, странно, а где статьи про библиотеки с "революционными ленивыми" списками для С++25 ))
А замечание мое такое — когда декларативность, в частности функциональное представление, преподносят демонстрацией Хаскела, то только отпугивают и запутывают заинтересовавшихся, а его мощь "категориальности", контроля типов или ленивости можно бы называть отдельным определением, для ясности. А функциональщина без лишних "заморочек" присутствует в Эрланге.

Конечно, Лисп развивался и в него встроили все, он "мульти". Его основы отобразили "функциональное программирование" по мотивам формализмов Черча, а это лямбды, функции, функторы, замыкания и тд. Удивлен сложившейся однобокостью, как будто теория категорий и вывод типов основы функциональщины, в Лиспе уже все основы были и в Эрланге они же...

Очень странная история, и это в 1977 году! А в 71-ом там же был Маккарти, цитирую энциклопедию:


Джон Маккарти — американский информатик, автор термина «искусственный интеллект» (1956), изобретатель языка Лисп (1958), основоположник функционального программирования, лауреат премии Тьюринга (1971) за огромный вклад в область исследований искусственного интеллекта.

Похоже, любители монад, приватизируют функциональный подход, а у него длинная история,… может Хаскелу нужна отдельная категория: "языки категорий", "категорианство", "категориальное программирование"?

Я Нелениво выполнил вручную итерации цикла и получил такую композицию
уменьшая влияние проблем в раскраске синтаксиса на суть:
qsort( X ) when X = [] -> []; 
qsort( [H | T] ) - >
         L = qsort([X || X <-T , X<H]),
         R = qsort([X || X <-T , X>=H]),
         L ++ [H] ++ R.

сверху все примеры с опечаткой были, тут устранено
Не, думаю там виной вселенский заговор, это Хром занимает все ресурсы драйверами всех типов видеокамер, что бы следить за человечеством в пользу Гугла.
Привлекли термины попавшие в заголовок статьи «циклы», «алгоритмы». Традиционно именно циклы используют в алгоритмах сортировки массивов. Можно пример «простой» сортировки (вставка, пузырек, выбор...), алгоритм которой должен состоять из двух циклов. Не хочу никого обижать, но действительно, очень желал бы увидеть, какой это будет «красивый, понятный, эффективный код». Только в рекурсивном выражении не нужно, в этой формулировке Эрланг уже получил приз за высокую «красивость и неэффективность», там вот одной строки хватает:
q([])->[];q([H|T])->[q([X<-T,X=<H])]++[H|q([X<-T,X>H])].

upd: даже раскраска исходного текста не выдержала, только первый символ смогла отделить, ха-ха, похоже, её реализовал тот, кто умеет красиво и эффективно одновременно.
upd2: почему только первый идентификатор функции выделяет цветом, почему далее по тексту, три раза встречается «кюю» и почему оно не выделилось…, а если вводить с новой строки — то сработает, получается лексемы не верно выделяет, парсер какой-то «левый»:
q([])->[];
q([H|T])->[q([X<-T,X=<H])]++[H|q([X<-T,X>H])].

upd3: как так, почему на профильном сайте такая ситуация, отмечаю текст необходимым языком, а это приводит к созданию картины неясности и недопонимания конструкций этого языка, а в дальнейшем это приводит к исключении его из списка языков, так уже Пролог «почил» уже более года назад, лично отмечено…
upd4: ну и на последок, а что показывает «индустрия», как это будет выглядеть в другом стиле:
q([])->[];q([H|T])->[q([X<-T,X=<H])]++[H|q([X<-T,X>H])].

Ясно, в декларативной парадигме, меня увлекает возможность формулировать описание проблемы, которое и является ее решением, это же превращение условий задачи в абстрактные элементы, которые должны сложиться в ответ.
А реализовать прологом этот fizzbuzz в обе стороны возможно, надо покорректнее сформулировать описание.
Спасибо, я могу ошибаться, совсем не углублялся в этот формализм, но форма записи напоминает знакомый Си++, где вместо указателя на базовый класс можно передать указатель на объект реализовавший наследника, а у него, ясно, все базовые операции должны присутствовать.
Я попробовал выделить, что абстрагируясь, погружаясь в суть корректных формулировок, есть возможность получать решения прямой и обратной задачи одновременно. Тут было сложение/вычитание, умножение/деление, которые выражаются единым правилом.
Представленное мной решение не «полно», оно не вычислит цель «для каких чисел на выходе будет fizz» или «для каких чисел на выходе будет fizzbuzz», вот так не сработает:
?- fizz_buzz(N, fizz).

Для уточнений формулировки потребуется новая статья, а Скала позволяет формализовать «обратную» и «прямую» задачу одним описанием?
Попробую точнее, деление без остатка — это существование натурального множителя для делителя, при умножении на который получим натуральное делимое. Реализация из статьи так не вычислялась, вот иная формулировка:
add(0,X,X).
add(X+1,Y,Z+1):-add(X,Y,Z).

mul(0, _, 0).
mul(X+1, Y, Z):- add(Z1, Y, Z), mul(X, Y, Z1).

%кратность на 3
?- mul(_, 0+1+1+1, 0+1+1+1+1+1+1).
true.
%кратность на 2
?- mul(_, 0+1+1, 0+1+1+1+1+1+1).
true.
%и не кратность
?- mul(_, 0+1+1, 0+1+1+1+1+1).
false.
Да, охота увидеть, что суть решения задачи в умении ее корректно формулировать. В этом пролог удобен.
По задаче нужно уметь «определить делимость натуральных чисел без остатка», в тексте приведена реализация умножения, можно бы было упростить так: «возможность умножить какое-то натуральне число на делитель и получить делимое», вот так:
?- mul( _, 0+1+1, 0+1+1+1+1).

такая цель подойдет, что бы узнать, что нет остатка от деления на 2 (0+1+1).
Конечно, на умелых абстракциях, полученных Тьюрингом и Черчем основана сегодняшняя цивилизация… Но все таки, природа натуральных чисел волновала еще и Пифагора с Аристотелем.
Спасибо, верное замечание )) Сколько в отрасли «недопонятых» формулировок, как часто реализуют системы несоответствующие требованиям, почему не удаётся воплощать грезы заказчиков, все плодятся паттерны, универсальные языки описаний, эМВэПэ и др… А тут демонстрация умения «абстрагироватся» — на нем и держится наш труд. В условии задачи используют «число делится на три», а это неявно подразумевало определенные ограничения, их поиск тут и представлен.

Information

Rating
Does not participate
Registered
Activity