[Ненормальное программирование, Разработка веб-сайтов, Программирование, Haskell] Зачем мы транспилируем Haskell в JavaScript
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Зачем нужна транспиляция в JavaScript
Привет, Хабр! Сегодня мы расскажем, почему мы пишем фронтенд на Haskell и компилируем его в JavaScript. Вообще говоря, подобный процесс называется транспиляцией:
Транспиляция — это процесс преобразования программы на языке X в эквивалентную программу на языке Y. В отличие от компиляции, языки X и Y находятся примерно на одном и том же уровне абстракции.
Зачем нужна транспиляция?
В общем случае можно выделить две основные цели транспиляции:
- Миграция между разными версиями одного языка. Языки программирования не стоят на месте, активно развиваются и обрастают новыми удобными фичами с каждой новой версией, которые хочется использовать. К сожалению, везде и сразу новые средства языка могут не поддержаваться, поэтому возникает вопрос об обратной совместимости версий. В данном случае такой межверсионный транспилятор производит что-то вроде "рассахаривания" (deshugaring) конструкций в более старые и обычно менее выразительные версии. Примером может служить Babel, переводящий код на JS в его подмножество, поддерживаемое браузерами. Возможно и преобразование в другую сторону, когда необходимо перевести проект на более новую версию языка, а делать вручную это долго и лень. Например, для транспиляции кода на Python 2.x в код на Python 3 есть 2to3.
- Перевод с одного ЯП на другой, исходя из требований рантайм системы и/или пожеланий разработчиков. Например, для исполнения в браузере требуется код на JS (чаще всего применяется на данный момент) или WASM (пока что менее распространён), а для разработки ставятся требования, которым лучше соответствует другой язык. Этот исходный язык может поддерживать уникальные механизмы, такие как автоматическое распараллеливание, или же вообще относиться к другой парадигме. Код, генерируемый транспайлерами, может быть как максимально похож на исходный (это упрощает отладку), так и стать неузнаваемым по сравнению с кодом на исходном языке. Существуют утилиты, позволяющие сопоставить резуьтат транспиляции с оригинальным кодом (например, SourceMap для JS).
Приведём несколько примеров:
- Языки для фротенд-разработки, транслируются в JS:
— TypeScript — надмножество JavaScript с опциональными аннотациями типов, которые проверяются во время транспиляции.
— CoffeeScript — более выразительный по сравнению с JS язык, в который добавлен синтаксический сахар в духе Python и Haskell.
— Elm — чисто функциональный язык со статической типизацией (и в целом похожий на Haskell), позволяющий создавать веб-приложения в декларативном стиле, который так и называется The Elm Architecture (TEA).
— PureScript — тоже чисто функциональный и статически типизированный язык с Haskell-подобным синтаксисом.
— ClojureScript — расширение языка Clojure (который, в свою очередь, диалект Лиспа) для веб-программирования на стороне клиента.
- Языки описания аппаратуры:
— Bluespec — высокоуровневый функциональный язык описания аппаратуры, изначально был расширением Haskell, транспилируется в Verilog.
— Clash — также функциональный, с похожим на Haskell синтаксисом, генерирует код на VHDL, Verilog или SystemVerilog.
— Verilator — в отличе от предыдущих двух, работает в другую сторону и преобразует подмножество Verilog в C++ или SystemC.
- Транспиляторы языков ассемблера для различных архитектур или под разные процессоры из одной системы архитектур (например, между 16-битным Intel 8086 и 8-битным Intel 8080).
Почему бы не вести разработку на чистом JS?
Как можно увидеть из приведённых выше примеров, разговор о транспиляции в целом неизбежно затрагивает трансляцию в JS. Давайте разберём более подробно, какие цели это преследует и какие может дать преимущества:
- Транспиляция в JS позволяет запустить приложение в веб-браузерах.
- Разработчики используют те же самые инструменты, что и для разработки бэкенда, поэтому не нужно изучать другие инфраструктуры библиотек, менеджеры пакетов, линтеры и т.п.
- Появляется возможность использовать ЯП, который ближе отвечает предпочтениям команды и требованиям проекта и получить чужеродные консервативному фронтенд-стеку механизмы, такие как строгая статическая типизация.
- Общую для фронтенда и бэкенда логику можно вынести отдельно и переиспользовать этот код. Например, подсчёт общей стоимости заказа может быть нетривиальным из-за специфики предметной области. На клиенте нужно отобразить стоимость заказа, а во время обработки запроса на сервере нужно всё заново перепроверить и пересчитать. Саму бизнес-логику подсчёта общей стоимости заказа можно написать один раз на одном языке и использовать в обоих местах.
- Используются механизмы кодогенерации и генерики, которые, например позволяют убедиться что сериализация и десериализация в JSON или даже бинарное представление будет работать без проблем. Мы использовали такой подход для ускорения разбора запросов, приводящих к большому объему парсинга, чем смогли в ряде случаев, улучшить производительность.
- Упрощается процесс отслеживания совместимости API между клиентом и сервером. При синхронной раскладке клиенсткого и серверного приложений, а также правильной работе с кэшами в браузерах, должны отсутствовать ситуации с несовместимостью, которые возможны при асинхронных выкладках. Например, если одна часть приложения обращается к другой по API, и API изменяется, есть шанс забыть об этих изменениях на клиенте и потерять какой-нибудь параметр запроса или отправлять тело запроса в неправильном формате. Этого можно избежать, если клиентское приложение написано на том же языке. В идеале оно даже не пройдёт компиляцию, если клиентская функция не соответствует текущей версии API.
- Разработчики одной квалификации участвуют и в бэкенд, и во фронтенд задачах, что дает дополнительную организационную гибкость для команд и увеличивает автобусный фактор. Так становится проще распределять задачи и нагрузку на каждого из членов команды. Это важно и когда нужен срочный фикс — самый "незагруженный" берёт задачу независимо от того, к какой части проекта она относится. Один и тот же человек может исправить и валидацию поля на фронтенде, и запрос к БД, и логику хендлера на сервере.
Наш опыт транспиляции в JS
При выборе инструментов для фронтенд-разработки мы принимали во внимание следующие факторы:
- Хотелось использовать язык со строгой статической типизацией.
- У нас уже существовала достаточно объёмная кодобаза для бэкенда на Haskell.
- Большинство наших сотрудников имеет серьёзный опыт промышленной разработки на Haskell.
- Мы хотели воспользоваться преимуществами одного стека.
На данный момент мы в Typeable ведём фронтенд-разработку на Haskell и используем веб-фрейморк Reflex и функциональное реактивное программирование (FRP). Исходный код на Haskell транспилируется в код на JavaScript с помощью GHCJS.
TypeScript и прочие расширения JS нам не подошли из-за недостаточно строгой типизации, не такой развитой системы типов, как в Haskell, да и в целом эти языки слишком радикально отличаются от привычных для нашей команды.
Reflex мы предпочли таким вариантам как Elm и PureScript в первую очередь из-за желания использовать тот же стек разработки, что и для бэкенда. Кроме того, Reflex позволяет не следовать определённой архитектуре приложений и в какой-то степени является более гибким и "низкоуровневым". Подробнее про сравнение Elm и Reflex можно прочитать в нашем посте на эту тему.
Выводы
Нам удалось получить те преимущества транспиляции в JS, о которых мы рассказали выше:
- Разработка всех частей проекта ведётся с использованием одного стека, а участники команды являются "универсальными" программистами.
- Упрощённо структура проекта представляет собой несколько пакетов: описание API, описание бизнес-логики, бэкенд и фронтенд. Первые два из них являются общими частями для фронтенда и бэкенда, значительная часть кода переиспользуется.
- Мы используем библиотеку servant, которая позволяет описать API на уровне типов и проверить во время компиляции, что, как обработчики на сервере, так и функции для отправки запросов на клиенте, используют правильные параметры нужных типов и соответствуют актуальной версии API (забыли поменять клиентскую функцию на фронденте — он просто не соберётся).
- Функции для сериализации и десериализации в JSON, CSV, бинарное представление и т.п. генерируются автоматически и одинаково на бекенде и фронтенде. Про API слой можно практически не думать.
Разумеется, есть и определённые трудности:
- Всё ещё приходится использовать вставки на чистом JS для работы с внешними плагинами.
- Отладка становится сложнее, особенно пошаговый режим. Однако такое требуется крайне редко, большинство ошибок оказывается в логике реализации.
- Меньшее количество документации по сравнению с фреймворками на JS.
Соавтор: Катерина Галкина
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Разработка мобильных приложений, Dart, Flutter] Dart 2.12: Sound null safety и Dart FFI отправлены на стабильный канал (перевод)
- [Разработка веб-сайтов, PHP, Программирование, IT-стандарты] Нам точно нужен фреймворк?
- [Программирование, Анализ и проектирование систем, IT-инфраструктура, Носимая электроника] Аналитика событий на опасном производстве, или зачем «Цифровому рабочему» Kafka, Esper и Clickhouse
- [Программирование, IT-инфраструктура, Big Data, R] IT Service Health Monitoring средствами R. Взгляд под иным углом
- [Разработка веб-сайтов] Рендеринг в веб (перевод)
- [Open source, Программирование, Администрирование баз данных, Интервью] «Представь, что ты нашел решение, про которое можешь сказать: оно лучшее в мире» — интервью с создателем ClickHouse
- [Программирование, *nix, Локализация продуктов, Kotlin, Изучение языков] Интернационализация и локализация приложения на Kotlin/Native
- [Программирование, Разработка под Android, Kotlin] Как можно использовать шейдеры в Android View и как Android View может использовать шейдеры (перевод)
- [Программирование] Как справиться с более чем двумя миллиардами записей в SQL-базе данных (перевод)
- [Программирование, C++] Новый поток в C++20: std::jthread (перевод)
Теги для поиска: #_nenormalnoe_programmirovanie (Ненормальное программирование), #_razrabotka_vebsajtov (Разработка веб-сайтов), #_programmirovanie (Программирование), #_haskell, #_haskell, #_javascript, #_transpilation, #_crosscompile, #_crosscompiling, #_webrazrabotka (web-разработка), #_webprogrammirovanie (web-программирование), #_blog_kompanii_typeable (
Блог компании Typeable
), #_nenormalnoe_programmirovanie (
Ненормальное программирование
), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_programmirovanie (
Программирование
), #_haskell
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:40
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Зачем нужна транспиляция в JavaScript Привет, Хабр! Сегодня мы расскажем, почему мы пишем фронтенд на Haskell и компилируем его в JavaScript. Вообще говоря, подобный процесс называется транспиляцией: Транспиляция — это процесс преобразования программы на языке X в эквивалентную программу на языке Y. В отличие от компиляции, языки X и Y находятся примерно на одном и том же уровне абстракции.
Зачем нужна транспиляция? В общем случае можно выделить две основные цели транспиляции:
Приведём несколько примеров:
Почему бы не вести разработку на чистом JS? Как можно увидеть из приведённых выше примеров, разговор о транспиляции в целом неизбежно затрагивает трансляцию в JS. Давайте разберём более подробно, какие цели это преследует и какие может дать преимущества:
Наш опыт транспиляции в JS При выборе инструментов для фронтенд-разработки мы принимали во внимание следующие факторы:
На данный момент мы в Typeable ведём фронтенд-разработку на Haskell и используем веб-фрейморк Reflex и функциональное реактивное программирование (FRP). Исходный код на Haskell транспилируется в код на JavaScript с помощью GHCJS. TypeScript и прочие расширения JS нам не подошли из-за недостаточно строгой типизации, не такой развитой системы типов, как в Haskell, да и в целом эти языки слишком радикально отличаются от привычных для нашей команды. Reflex мы предпочли таким вариантам как Elm и PureScript в первую очередь из-за желания использовать тот же стек разработки, что и для бэкенда. Кроме того, Reflex позволяет не следовать определённой архитектуре приложений и в какой-то степени является более гибким и "низкоуровневым". Подробнее про сравнение Elm и Reflex можно прочитать в нашем посте на эту тему. Выводы Нам удалось получить те преимущества транспиляции в JS, о которых мы рассказали выше:
Разумеется, есть и определённые трудности:
Соавтор: Катерина Галкина =========== Источник: habr.com =========== Похожие новости:
Блог компании Typeable ), #_nenormalnoe_programmirovanie ( Ненормальное программирование ), #_razrabotka_vebsajtov ( Разработка веб-сайтов ), #_programmirovanie ( Программирование ), #_haskell |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:40
Часовой пояс: UTC + 5