March 18th, 2012

flow

Юзабилити для языков программирования - 2

Продолжая http://justy-tylor.livejournal.com/173996.html отвечаю на просьбу ругать Haskell.

Как правило, критика Хаскеля сводится к религиозным спорам на тему pure functional подхода и ручной работы с эффектами. Здесь я не буду это рассматривать. Разные проекты, разные требования. Обратимся к другим проблемам.

1. Синтаксис работы с типами.

instance (Data k, Data a, Ord k) => Data (Map k a) where ...
Перевод: Map k a является инстансом тайпкласса Data, если k и a являются инстансами тайпкласса Data, и k является инстансом тайпкласса Ord. После where описываются специфичные для данного инстанса операции.

Много слов про ямб, хорей и прочие детали, и только в конце идентифицируется Map. Прямо как в C++ (Java, C#, ...). И чтение требует ровно тех же оккультных навыков. Счастье хаскеллистов в том, что им реже приходится эти типы упоминать. Но когда всё же приходится, то... :)

2. Карринг.

Эта особенность присутствует не только в Haskell, но и в других функциональных языках (OCaml, F#, ...).

Update: Если вам не знаком термин карринг (currying), можете прочитать о нём в http://fprog.ru/2009/issue3/eugene-kirpichov-elements-of-functional-languages/

Для примера рассмотрим работу с Data.Map.

x = findWithDefault fdef key funcs -- нормальная ситуация, findWithDefault возвращает функцию по ключу key из funcs, или fdef при её отсутствии
x = findWithDefault fdef key -- ошибка идентификации, в данном выражении не осуществляется findWithDefault, а только создаётся замыкание, которому в дальнейшем можно передать funcs для осуществления поиска.
x = findWithDefault fdef key funcs param -- серьёзная ошибка идентификации, x является результатом применения найденной функции к param, а не результатом поиска.

Таким образом можно незначительно экономить на комбинаторах и макросах. Но активное использование карринга (которое пропагандируется начиная со стандартных библиотек) значительно приближает упомянутые языки к write-only languages (APL, J, K, ...).