
--
Хаскелисты Rust ругают частенько за недофункциональность - изначально императивный язык, да-да! Но в Rust есть многое, что присутствует в больших ФП-языках, и это не "эти ваши академические штучки", а исключительно полезные вещи - я про traits и ограниченный параметрический полиморфизм говорю. Да, в Rust нет HKT и не будет никогда, скорее всего. Но даже то, что есть, очень сильно помогает управлять сложностью через абстракцию.И именно средства для управления сложностью кода делают язык пригодным для реализации на нём действительно больших проектов!
С этой точки зрения плох Go - абстрагирование там не в чести и встроенные средства для построения абстракции очень бедны (из, можно сказать, нет). А это означает, что большие проекты состоят из копипаст (в т.ч. и из копипаст ошибок!) и местных велосипедных ренеший (в Go тоже не принято переиспользовать чужой опыт, культура поощряет "скопировать к себе если уж сам не хочешь писать"). Процедурные языки имеют инструмент, созданный для управления сложностью - ООП. Да, "правильно готовить" его умеет не каждый, но инструмент очевидно работает - иначе его бы выбросили на свалку истории. В Go нет ООП но и нет альтернативы.
Теперь смотрим на ФП. Было когда-то сказано "лучше иметь один тип и сто функций для работы с ним, чем десять типов и по десять функций для работы с каждым" - сказано это было в контексте Lisp, но работает и для ФП в целом. И если "один тип на все случаи жизни", это странная идея, то вот единый вокабулярий для работы с разыми типами, это отличная вещь!
И вот тут мы подходим к Elm. Единый вокабулярий отнюдь не означает "у нас везде map, просто это
List.map, Maybe.map и т.п." - это разные функции для работы с разными типами. Т.е. нет возможности писать обобщённый код. И абсолютно не важно здесь, как эти функции называются (пусть даже и понятно и "читаемо")! Нельзя написать "библиотеку, которая обобщённо работает с коллекциями" и подобные сугубо полезные в реальных проектах вещи!И всё только осложняется тем, что в Elm типизация статическая. Потому что в динамически типизированном ЯП мы можем хотя бы ad hoc полиморфизм силами "утиной типизации" сделать или на крайний случай прямо в функции решить, как с переданным типом работать (не сильно гибко и точно не особо расширяемо, но относительно обобщённый код писать позволяет). А при старической типизации в Elm мы имеем лишь "неограниченный" параметрический полиморфизм: мы всегда всё знаем о структуре, но никогда о "содержимом" типа. А значит мы не сможем без привнесения излишней сложности написать, скажем, функцию
sort : List a -> List a - мы по построению не знаем ничего об a и не можем знать при текущей модели. Да, местный ad hoc есть в виде comparable, но с чего это автор решил, что ad hoc полиморфизм нужен только в тех местах, где он сейчас есть? Примеров могу привести много - и все из реальной жизни.Так что же хорошего в том, что мы имеем ФП, но такой, где функции (и типы) пользователя - объкты второго сорта; где автор решил, что такие-то типы comparable, а пользовательские - нет; где автор stdlib может писать обобщённый код - внутри stdlib - а пользователи не могут?! И не нужно говорить о "сложности для новичков" и "те, кому надо, пойдут в другие языки" и в этом же контексте "у нас - успешный язык для решения реальных задач!". Это лукавство. Потому что зрелый язык помогает решать проблемы, а не создаёт искуственно препятствия для решения оных.
--
P.S. Это похоже на "нытьё", но я правда так считаю. Часто бываю непонят или неуслышан.













