Почему хаскель не подходит для скриптования?

Posted on June 13, 2014 with tags: haskell, манифест.

Прежде чем обсуждать недостатки такого безусловно примечательного инструмента следует определиться с таким самоочевидным понятием как скриптование. Речь пойдёт в первую очередь о так называемых скриптах пользователя: небольших программах обеспечивающих интерфейс взаимодействия пользователя и более сложной системы. Например скрипты emacs’а, vim’а или даже acpid’а. В определённой степени можно говорить и командной оболочке операционной системы в принципе с некоторыми оговорками. Следует различать пользовательские скрипты и приложения для одного запуска: последние могут сколь угодно сложны, громоздки, запутаны, не очевидны и нечитабельны, поскольку читать их никто не будет и пишутся они обычно на одном дыхание, а со своими скриптами вам скорее всего ещё долгое время жить. Итак пользовательский скрипт это программа:

Для таких задач традиционно используются shell, lua, js, scheme и прочие языки поразительно схожие с этими синтаксисом и семантикой (хотя некоторые умудряются для этого сравнительно успешно использовать целый python). Что объединяет эти языки? Слабая (у всех кроме scheme) динамическая типизация и позднее связывание. Оно и понятно, считается что если убрать из программы аннотацию типов то она станет выглядеть проще. Однако на сдачу мы получаем невозможность проверить хотя бы наличие вызываемых функций и существование используемых переменных не говоря уж о разумности применения одного к другому. Поскольку покрывать тестами подобного рода код будут немного позже того как к нему напишут документацию, то ситуация выглядит так себе.

При этом следует понимать, что статическая типизация и ранее связывание вообще говоря совсем не требуют аннотации типов. Компилятор зачастую может понять какой тип имеет то или иное выражение просто из контекста используемых функций. Компилятор может осуществлять вывод типов даже в таком языке как C++, где система типов вообще один из кругов Ада. Для более простого языка это осуществить ещё проще. Всё что ему нужно это твёрдая уверенность, что в середине выполнения программы не появятся новые функции, а семантика существующих типов не изменится. Довольно забавно, но для очерченных нами задач это практически всегда верно поскольку для решения простых задач такие динамические возможности едва ли понадобятся, а сложные мы вроде бы решать и не собирались3.

Теперь посмотрим в свете наших задач на Haskell. Итак Haskell это ленивый, функциональный язык программирования с полиморфизмом на классах типов:

Плюс сопоставление с образцом, которое у конкурентов как правило отсутствует (ну кроме scheme и прочих лиспов). Что не так? А не так примерно следующее:

Пущей объективности ради следует заметить, что языки из круга конкурентов совсем не обязательно лишены подобных недостатков. И тем не менее будем считать что всё дело именно в них. Если всё перечисленное плохо и не нужно, то что нужно?


  1. Ну или у вас просто нет возможности поправить код системы. Но тогда горе побеждённым! Какой смысл обсуждать достоинства и недостатки brainfuck, если это единственный доступный вам способ изменить поведение вашей системы?

  2. Угу. Например в код emacs на elisp встроено небольшое ядро на C.

  3. Существует спорное утверждение, что динамика очень нужна для создание EDSL’ей которые действительно позволяют повысить простоту кода и довольно эффективно съесть сложность и громоздкость кода.

  4. Иначе у нас бы использовалось целочисленное деление.

  5. Да-да. Это семейства типов. Но они выглядят более громоздкими. Функциональные зависимости более лаконичны что-ли.