Artem Chuprina <r...@lasgalen.net> writes: > Dmitrii Kashin -> debian-russian@lists.debian.org @ Wed, 07 Oct 2015 > 02:07:07 +0300: > > DK> За время работы с ним меня приятно удивило после Haskell: > > DK> 1) Позволяет более просто комбинировать функциональное и императивное > DK> программирование: не надо изворачиваться монадами, чтобы добиться > DK> последовательного выполнения команд. > > ... > > а зачем, собственно, добиваться последовательного выполнения никак не > связанных между собой команд?
Я думаю, тут есть недоразумение. Требование последовательного выполнения определённых команд как раз и определяет связь между ними. Если конечно не считать, что связь -- это "результат А нужен для вычисления B". Тут важно понять, что императивное программирование -- это именно программирование с изменением состояния системы. Зачем это нужно? Ну, бывают разные случаи. Бывает, что это повышает производительность. В случае большого словаря создание его дубликата при изменении значения одного ключа создаёт очень большие накладные расходы. Бывает, что это упрощает описание алгоритма. Например, если Вы реализуете программу, алгоритм которой описан в императивном стиле в некоторой статье, то логично пользоваться тем же представлением, что и автор. Бывает, что без этого обойтись невозможно. Такое случается, когда Ваша программа должна некоторым образом взаимодействовать со внешней средой. Вот пишете Вы, допустим, сборочную систему, и Вам принципиально важно, чтобы были выполнены последовательно сначала git clone, а потом git checkout. > DK> 2) Позволяет таки определять полиморфные функции. Да, это нарушение > DK> системы типов, но если этим не злоупотреблять, то это даже удобно. > > Какого именно вида полиморфных функций? В хаскеле их минимум два (а с > generics, пожалуй, и все три). Прошу прощения, ошибся. Я уже начал подзабывать Haskell. Да, в Haskell есть полиморфные функции. Но вот сейчас я вспомнил, чего я действительно не видел в Haskell, и что очень облегчает мне жизнь сейчас. Это опциональные аргументы при сопутствующих полноценных возможностях каррирования. Мне вот достался в наследство проект, который в виду крайне сумбурного развития имеет ужасную архитектуру, и работает с горем пополам. Благодаря возможности описания опциональных аргументов у функций, я могу дополнять их функционалом, не меняя при этом их поведения в старом коде. По поводу каррирования, то вот к примеру можно определить функцию со двумя опциональными аргументами: let funA ?a ?(b=1) c = match a with | None -> b*c; | Some a -> a+b*c И после этого каррировать её вот так:\ let funB = funA ~a:None ~b:2 При этом "funB 1" будет эквивалентна "funA ~b:2 1" Вот тут ещё можно посмотреть очень интересное мнение: http://blog.ezyang.com/2010/10/ocaml-for-haskellers/ > DK> Я в своё время с Вашей подачи пытался взять Haskell наскоком. Увы, он > DK> меня расстроил по целому ряду причин. Если хотите, могу рассказать. > > Было бы интересно. Я его и сам осваивал небыстро, и кое-что открываю в > нем до сих пор, пятый год уже. (Кое-что из этого, впрочем, и > появилось-то в этом году.) Если Вы не возражаете, я сегодня на работе сделал некоторую заготовку для ответа Вам, но адаптировать её и выверять у меня уже нет сил. Потому помещаю как есть. ******** Как Вы знаете, некоторое время тому назад я с Вашей подачи пытался работать на Haskell, и предпринял даже попытку написать дипломную работу с использованием этого языка. В то время язык оказался неподходящим. Я, конечно, разработал чисто функциональные алгоритмы, которые сильно упростили мне проектирование будущих версий программы, но я столкнулся вот с чем: Программа была научная, и её целью было исследование метода. Так вот: очень, очень сложно производить дебаг алгоритма, когда вычисления производятся ленивым образом. Я уверен, что Haskell -- язык хороший, но в основном для алгоритмов, в которых Вы заранее можете быть уверены: либо достаточно простых (простых не значит коротких), либо строго доказанных математически. Промучившись с этим делом полгода, я отошёл от этой задачи в сторону Common Lisp'а, который хотя и динамически типизирован, сэкономил мне кучу времени макросами и приличным FFI-ем (как подружить с которым Haskell я понятья не имею, ибо опять же, ленивость). Сейчас я работаю в основном на Racket Scheme, Emacs/Common Lisps и Ocaml. Последний выглядит для меня примерно как Haskell, только без ленивости. Синтаксис выразительный, но логика вычислений проще поддаётся осмыслению, и дебаг также не вызывает трудностей. > Я Вам открою, наверное, страшную тайну: в хаскеле вообще невозможно > добиться последовательного выполнения команд, кроме как через > зависимость "результат A нужен для вычисления B". В монадах на сей > предмет нет ничего волшебного. Даже в монаде IO. Я когда-то, посмотрев > на ее реализацию и осознав, что она такое, ухитрился даже нарисовать > тест, который это демонстрировал. Ну, вот видите. Принудительная ленивость по умолчанию порождает ряд очень не очевидных проблем, а плюсов её навязывания я не ощущаю. Я не утверждаю, что они не решаемы. Возможно, я просто не смог до конца разобраться. Но рекомендованного Вами "Learn Haskell for Great Good" мне лично не хватило, чтобы уверенно работать.
signature.asc
Description: PGP signature