LINUX.ORG.RU

GHC 8.8.1

 , ,


5

9

Тихо и незаметно, вышла новая версия известного компилятора языка программирования Haskell.

Среди изменений:

  • Поддержка профилирования на 64-битных системах с Windows.
  • GHC теперь требует LLVM версии 7.
  • Метод fail окончательно вынесен из класса Monad, теперь он находится в классе MonadFail (финальная часть MonadFail Proposal).
  • Явное применение типа (type application) теперь работает и для самих типов, а не только для значений.
  • forall теперь является ключевым словом вне зависимости от контекста, что позволяет использовать его в type families и rewrite rules.
  • Улучшен алгоритм компоновки кода для x86.
  • Множество других изменений.

>>> Полный список изменений

>>> Гайд по миграции кода на новую версию

>>> Скачать

★★★★★

Проверено: jollheef ()
Последнее исправление: Virtuos86 (всего исправлений: 4)
Ответ на: комментарий от q0tw4

Вот с LLVM как раз получается лучше, поскольку он достаточно низкоуровневый, чтоб эффективно реализовать любой необходимый языку рантайм

Расскажи мне, пожалуйста, какой рантайм на LLVM реализовывается для хацкелла?

hateyoufeel ★★★★★
() автор топика

Фсем чмоке в этом чатике!

dimgel ★★★★★
()
Ответ на: комментарий от anonymous

Очень показательно. Сразу видно какой язык используется в продакшене, а какой ...

anonymous
()
Ответ на: комментарий от vertexua

Не, я тут себе коллекцию DRM-free от Manning собираю и бэкапы в локальную сеть в квартире, чтобы Роскомнадзор мою библиотеку не побил.

Так что не проблема и купить, тем более, что сейчас стоит всего 18$.

Deleted
()
Ответ на: комментарий от anonymous

Есть язык, спроектированный определенным образом. Он является цельным продуктом, способом мышления и тп. И тут приходит некий Вася и говорит, а давайте я возьму ваш язык и запущу его поверх JVM. И в процессе обнаруживает, что уникальные фичи языка невозможно реализовать поверх имеющихся в VM механизмов не прибегая к ресурсозатратной интерпритации (ну или тормозного рефлекшена например). И тогда он решает урезать язык. Итого мы получаем джаву со скобочками, которая к тому же плохо совместима с другим джава кодом из-за использования своих коллекций и леса граблей. Такое имеет смысл делать только для андроида, поскольку на последнем сложно завести VM, написанную на сях и там просто нет выбора. Если же мы на десктопе, так зачем нужна JVM? Большой набор пакетов? У си либ поболее будет, да и развиваются они активнее. Проще взять родную VM и FFI к сишной либе, чем огрызок языка на JVM и возню с системами сборки

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

интерпритации

Вас приветствует орфографический бот!

В ваших постах, в целом вполне грамматически корректных, наблюдается последовательно ошибочное написание слова «интерпретация» и его производных. Возможно, вам будет интересно, что правильно это слово (и его производные) пишется через «е»: интерпретация, интерпретатор, интерпретировать.

anonymous
()
Ответ на: комментарий от q0tw4

И в процессе обнаруживает, что уникальные фичи языка невозможно реализовать поверх имеющихся в VM механизмов не прибегая к ресурсозатратной интерпритации (ну или тормозного рефлекшена например). И тогда он решает урезать язык.

ANSI Common Lisp реализован в полном объёме (ABCL). Scheme тоже (SISC).

Итого мы получаем джаву со скобочками, которая к тому же плохо совместима с другим джава кодом из-за использования своих коллекций и леса граблей.

Так то же самое и с POSIX. Перефразируя тебя, получаем си со скобочками, который плохо совместим с другим си кодом из за использования своих структур данных и леса граблей.

У си либ поболее будет,

Спорное утверждение. Можно пример аналога на Си для Hibernate, Xerces2, Hadoop?

monk ★★★★★
()
Ответ на: комментарий от monk

XML парсеров завались начиная от libxml2, ORM на плюсах - дело не благодарное (слишком расхлябанный язык, чтоб пытаться скодогенерить иерархию классов) и все пишут руками. Распределенные вычисления может быть лучше писать на ерланге. И я не говорил что для каждой джава либы есть аналог на сях. Просто JVM как платформа взлетела не настолько высоко, чтоб пихать её везде. Впрочем андроид как раз пример задачи, в которой без JVM в принципе не обойтись, возможно есть задачи, в которых она со своими либами даст настолько значительный выигрыш в скорости разработки, что имеет смысл. Но если ты знаешь, что должен узать JVM, то ты уже не сомневаешься в выборе и не нуждаешься в моих советах.

q0tw4 ★★★★
()
Ответ на: комментарий от aeralahthu

Вот например котлин язык не плохой и желание писать на нём вполне может считаться доводом в пользу JVM. Использовать огрызок вроде Clojure имеет смысл только если JVM уже выбрана к использованию и то незачем, так как есть котлин

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

Использовать огрызок вроде Clojure

По фактам что не так с Clojure? И попрошу без повторений своей мантры «это не лисп, это не лисп», нужны конкретные доводы.

anonymous
()
Ответ на: комментарий от q0tw4

Спасибо, но я скобочки люблю. А JVM не люблю и не знаю. Так что, если всё-таки когда-нибудь придётся писать под неё, в первую очередь буду рассматривать ABCL или SISC или ещё какой полноценный лисп, если есть. Во вторую — Clojure. А уж потом остальные JVM-языки. Но, надеюсь, никогда не придётся.

aeralahthu
()
Ответ на: комментарий от abcq

Выглядит как какой-то файл конфигурации для неофита.

Так я и есть неофит :)

есть ли какой-то более вменяемый код?

Вот тут простые примеры, а тут посложнее.

Odalist ★★★★★
()
Ответ на: комментарий от hateyoufeel

Понятно, что в Clojure нет ленивости иначе пришлось бы ещё монаду IO изобретать. А так в Clojure используются Lazy Sequences и функции по типу map, filter, range возвращают ленивые последовательности, иными словами ленивость реализована на уровне данных. Для хвостовой рекурсии используется специальная форма recur, на самом деле вместо имени рекурсивной функции в теле этой функции нужно всего лишь написать recur и рекурсия развернётся в цикл

anonymous
()
Ответ на: комментарий от anonymous

Для хвостовой рекурсии используется специальная форма recur, на самом деле вместо имени рекурсивной функции в теле этой функции нужно всего лишь написать recur и рекурсия развернётся в цикл

Прикольно. В интернете полно информации, а ложные представления все так же сильны.

Не любая хвостовая рекурсия развернется в цикл _целевого_ языка, не любая. Хвостовая рекурсия эквивалентна циклу определенной воображаемой машины (см. PAIP), но это совсем не то же самое, что цикл такого _целевого_ языка, как clojure.

Контр-пример: косвенная рекурсия, которая естественным образом возникает при использовании продолжений. Вот, фиг ее сможет записать кто на java, не то, что на clojure или scala. Тем менее, в рамках упомянутой воображаемой машины из PAIP там действительно будет нечто похожее на цикл во время исполнения.

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 2)
Ответ на: комментарий от anonymous

Скажем так, записать так, чтобы было эффективно. В scala вон пытались реализовать через трамплин, но ничего хорошего, судя по всему, из этого не вышло.

dave ★★★★★
()
Ответ на: комментарий от dave

Хвостовая рекурсия эквивалентна циклу определенной воображаемой машины

Разве? Насколько я помню, любую хвостовую рекурсию можно реализовать циклом. Циклы в JVM есть.

Контр-пример: косвенная рекурсия, которая естественным образом возникает при использовании продолжений.

Можно пример кода? Вообще, продолжений ни в clojure ни в Common Lisp нету. Можно ли пример без них?

monk ★★★★★
()
Ответ на: комментарий от q0tw4

XML парсеров завались начиная от libxml2

Он разве уже реализовал DOM Level 3, Namespaces 1.1 и SAX 2.0.2? Недопарсеров завались, а как только начинаешь искать хоть один, соответствующий всем стандартам, так остаются только реализации на Java.

Работа с XLIFF? Тоже XLIFF 1.2 Core только Java. Для остального велосипеды разного уровня недоделанности.

Работа с OOXML? Самая полная библиотека Apache POI. Только Java.

ORM на плюсах

При чём тут плюсы? Мы же сравниваем с «взять родную VM и FFI к сишной либе». Плюсы через FFI недоступны (если не считать несколько языков непосредственно поверх C++).

возможно есть задачи, в которых она со своими либами даст настолько значительный выигрыш в скорости разработки, что имеет смысл. Но если ты знаешь, что должен узать JVM, то ты уже не сомневаешься в выборе и не нуждаешься в моих советах.

То есть ты согласен, что утверждение «Если же мы на десктопе, так зачем нужна JVM? Большой набор пакетов? У си либ поболее будет, да и развиваются они активнее. Проще взять родную VM и FFI к сишной либе, чем огрызок языка на JVM и возню с системами сборки» ложно?

monk ★★★★★
()
Ответ на: комментарий от dave

И cl-cont вспомни!

Лучше не надо. Те супертормоза пример, как не надо делать. Уж лучше продолжения через потоки.

monk ★★★★★
()
Ответ на: комментарий от monk

Это не матлогика. Тут нет чисто ложных и чисто правдивых высказываний. Имеется ввиду в большинстве случаев

q0tw4 ★★★★
()
Ответ на: комментарий от dave

Не могу найти там утверждения, что хвостовую рекурсию можно реализовать циклом только в виртуальной машине PAIP.

monk ★★★★★
()
Ответ на: комментарий от q0tw4

Имеется ввиду в большинстве случаев

???

Случаев чего? Утверждение «У си либ поболее будет, да и развиваются они активнее.» вроде для нашей вселенной либо истинно (если у си больше более развитых либ) либо ложно (если у си их меньше). Мы же не про параллельные миры говорим?

Я вообще не припомню сишную либу, которая бы активно развивалась в 2010-2020 годах, если не считать libsystemd и драйверы linux.

monk ★★★★★
()
Ответ на: комментарий от monk

Случаев чего?

Проще взять родную VM и FFI к сишной либе, чем огрызок языка на JVM и возню с системами сборки

q0tw4 ★★★★
()
Ответ на: комментарий от monk

Я вообще не припомню сишную либу, которая бы активно развивалась в 2010-2020 годах

Ну во-первых я С++ное считаю тоже сишным, у многих С++ либ есть сишный враппер, у многих (например gdal) С++-ный код спрятан в привате, наружу торчат только сишные апи

q0tw4 ★★★★
()
Ответ на: комментарий от monk

Плюсы через FFI недоступны (если не считать несколько языков непосредственно поверх C++).

На самом деле, это возможно, только очень через задницу. Ради примера можешь посмотреть inline-c-cpp для того же хацкелла.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от Odalist

ну я себя неофитом вообще-то подразумевал...

abcq ★★
()
Ответ на: комментарий от hateyoufeel

На самом деле, это возможно, только очень через задницу.

Я в курсе. Я Qt к Common Lisp'у прикручивал.

Ради примера можешь посмотреть inline-c-cpp для того же хацкелла.

Как и ожидалось:

  , ctxOutput = Just $ \s -> "extern \"C\" {\n" ++ s ++ "\n}"
monk ★★★★★
()
Ответ на: комментарий от q0tw4

Проще взять родную VM и FFI к сишной либе

Ну вот оказалось, что в большинстве случаев явовская либа работает лучше.

чем огрызок языка на JVM и возню с системами сборки

Зачем огрызок? Есть полнофункциональные языки: ABCL, SISC. Да и Scala тяжело огрызком назвать.

и возню с системами сборки

Вот я уже второй месяц долбусь с воспроизводимой сборкой GTK. В Linux не получается сделать GTK в папке программы (а системный может быть не той версии), в Windows вообще непонятно как собирать.

В Java в этом смысле всё на порядок проще.

monk ★★★★★
()
Ответ на: комментарий от q0tw4

у многих (например gdal) С++-ный код спрятан в привате, наружу торчат только сишные апи

Если брать именно gdal, то у него и Java API есть.

monk ★★★★★
()
Ответ на: комментарий от monk

Вот простейший случай косвенной хвостовой рекурсии при условии, что оператор (>>) является хвосторекурсивным, что справедливо для монады Cont и ее производных:

whileM :: Monad m => m Bool -> m () -> m ()
whileM p m =
  do a <- p
     if a
       then return ()
       else m >> whileM p m

Это «функциональный» вид оператора while, знакомого по другим языкам. Например, такое определение использует Async из F# при трактовке while.

Это _не_ разворачивается в цикл ни в F#, ни в C#, ни в Java, ни даже в Haskell. Но в Haskell это будет эквивалентно циклу. В F# зависит от реализации виртуальной машины CLR, поддерживает ли она честную настоящую оптимизацию хвостового вызова, что не всегда справедливо.

Кстати, в частности из-за while был затык в scala, когда там вводили плагин продолжений. Это можно отследить по статьям команды Одерского. В общем, у команды scala так в итоге ничего и не получилось из-за того, что в JVM нет такой оптимизации, и по видимому никогда не будет.

dave ★★★★★
()
Ответ на: комментарий от monk

Лучше не надо. Те супертормоза пример, как не надо делать. Уж лучше продолжения через потоки.

Тем не менее, там разворачивается код в хвостовою рекурсию, правда, методом очень грубой силы, но куда деваться - common lisp же! Поясню. Цикл loop преобразуется в такую дикую императивщину, что там становится просто чудовищно неэффективно использовать continuation-passing style (CPS). Было бы гораздо эффективнее переписать цикл через рекурсию, и уже потом пропустить через жернова CPS. Для справки: нотация do из Haskell для монады Cont как раз переписывает автоматически код в стиле CPS. Ладно, это все лирика.

dave ★★★★★
()
Ответ на: комментарий от anonymous

Трамплин может помочь с TCO, но его реализации обычно неэффективны, как мне кажется.

dave ★★★★★
()
Ответ на: комментарий от dave

Перепутал условие с его отрицанием в whileM. Ну, да ладно! Надеюсь, смысл понятен.

dave ★★★★★
()
Ответ на: комментарий от monk

Не могу найти там утверждения, что хвостовую рекурсию можно реализовать циклом только в виртуальной машине PAIP.

Только сейчас разглядел эту дичь. Ты зачем так выдумываешь сам столько?)

dave ★★★★★
()
Ответ на: комментарий от dave

Это получается

(defun whileM (p m)
  (let ((a (p)))
    (if a '()
          (progn 
            m 
            (whileM p m)))))

Такое даже SBCL на x86 в цикл разворачивает. И ABCL на JVM.

monk ★★★★★
()
Ответ на: комментарий от monk

Еще вспомнилось про cl-cont. Он преобразует к CPS что надо, и что не надо, причем последнего даже больше. На самом деле, с CPS все не так плохо, если умеючи. Что мне нравится в Haskell, там все будет ограничено рамками нотации do. Если говорить о скорости, то разница будет отличаться на порядки в зависимости от задачи.

dave ★★★★★
()
Ответ на: комментарий от monk

Не PROGN! Монадическая связка там должна быть! Ты вот вроде бы здесь на ЛОРе блистал много раз знанием Haskell. Где же оно? Куда подевалось?)

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)
Ответ на: комментарий от dave

Ты зачем так выдумываешь сам столько

Так ты же сам пишешь: «Хвостовая рекурсия эквивалентна циклу **определенной** воображаемой машины». Если согласен на «циклу **любой** целевой машины», то вопросов нет. Но циклы JVM тогда тоже подходят.

monk ★★★★★
()
Ответ на: комментарий от monk

Категорически не согласен на «цикл целевой машины». В этом и вся соль.

dave ★★★★★
()
Ответ на: комментарий от monk

Тут не квантор «для всех». Тут квантор «существует».

dave ★★★★★
()
Ответ на: комментарий от dave

Монадическая связка там должна быть!

Для IO: a >> b == (progn a b).

Для произвольной монады

(defun whileM (p m)
  (>>= (p) (lambda (a)
             (if a (return a)
                   (>> m (whileM p m))))))
вызов (whileM p m) не является хвостовым, если >> является функцией.

Для Haskell из-за ленивости он может быть хвостовым, если монада эквивалентна progn. Но тогда компилятор имеет достаточно информации для явного преобразования в цикл для любого целевого языка с циклами или условными переходами.

monk ★★★★★
()
Ответ на: комментарий от dave

Он преобразует к CPS что надо, и что не надо, причем последнего даже больше.

Наоборот, недостаточно. Только то, что внутри WITH-CALL/CC.

monk ★★★★★
()
Ответ на: комментарий от dave

Что мне нравится в Haskell, там все будет ограничено рамками нотации do.

В Haskell та же проблема. Что толку от «callCC $ \exit -> », если из map его вызвать нельзя.

monk ★★★★★
()
Ответ на: комментарий от monk

Даже не так.

(defun whileM (p m)
  (>>= p (lambda (a)
           (if a 
               (return null)
               (>> m (whileM p m))))))

Для нормального вычисления с монадой-лямбдой

(defun >>= (a p) (lambda () (funcall (p (funcall a)))))
(defun return (r) (lambda () r))

(defun >> (a b) (>>= a (lambda (x) b))) 
== (lambda () ((lambda (x) b) (a)))) 
== (lambda () (let ((x (funcall a))) (funcall b)))
== (lambda () (funcall a) (funcall b))

преобразуется в

(defun whileM (p m)
  (lambda ()
    (funcall 
      (lambda (a)
         (if a 
             (return a)
             (>> m (whileM p m))))
      (funcall p))))
=>
(defun whileM (p m)
  (lambda ()
    (funcall 
      (let ((a (funcall p)))
        (if a 
            (lambda () null)
            (>> m (whileM p m))))
=>
(defun whileM (p m)
  (lambda ()
    (funcall 
      (if (funcall p) 
          (lambda () null)
          (lambda () (funcall m) (funcall (whileM p m)))))))
И всё. whileM изнутри никак в конечно-хвостовую позицию не поставить.

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.