LINUX.ORG.RU

Glasgow Haskell Compiler 9.12.1

 , ,

Glasgow Haskell Compiler 9.12.1

0

6

Привет, ЛОР!

Тихо и незаметно вышла новая версия великолепного компилятора языка Haskell. GHC развивается сообществом разработчиков с 1992 года и поддерживает компиляцию языка Haskell в нативный код как напрямую, так и с использованием инструментария LLVM.

Среди особенностей новой версии:

  • Расширение языка OrPatterns, позволяющее давать общий обработчик нескольким веткам сравнения по образцу.
  • Поддержка многострочных строковых литералов через специальный синтаксис: """строка""".
  • В бэкенд компилятора добавлены экспериментальная поддержка архитектуры RISC-V и поддержка SIMD инструкций для архитектуры x86 (ранее требовалось использование LLVM).
  • Удалена поддержка 32-битных версий ОС Windows, macOS и iOS. Поддержка 32-битных систем на базе Linux и BSD нетронута.
  • Улучшена работа сборщика мусора. В некоторых случаях скорость работы программ может увеличиться на 25%.
  • И множество других мелких фич, багфиксов и так далее.

>>> Скачать

>>> Подробности

★★★★★

Проверено: dataman ()
Последнее исправление: CrX (всего исправлений: 4)
Ответ на: комментарий от monk

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

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

А вброс-то хороший. Все кинулись объяснять соревноваться.

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

Товарищ писал на нём инструментарий проектирования камней в рамках стартапа. Насколько я знаю, успешно.

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

Монада — это моноид

Моноид — полугруппа с единицей

А вот теперь мне стало интересно. Что является единицей для монады IO? И что является умножением для монады Maybe?

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

Тогда эта функция должна входить в множество, на котором определена монада. Но монада списка чисел определена на множестве чисел. И у списка элементов, рассматриваемого как моноид, умножением будет сцепление списков, а единицей пустой список, но никак не функция.

Можно представить моноид на множестве функций с операцией композиции в качестве умножения. Для него действительно единицей будет identity. Но, например, монада Maybe никак не представима в виде такого моноида.

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

Единица она потому, что ничего не делает, кроме как оборачивает значение:

data MyMaybe a = MyJust a | MyNothing deriving Functor

instance Applicative MyMaybe where
  pure = MyJust
  MyNothing <*> _ = MyNothing
  _ <*> MyNothing = MyNothing
  MyJust f <*> MyJust x = MyJust $ f x
dura4ok11
()
Ответ на: комментарий от monk

Тогда эта функция должна входить в множество, на котором определена монада. Но монада списка чисел определена на множестве чисел.

Вот тут есть довольно хорошее объяснение для Scala: https://rockthejvm.com/articles/a-monad-is-a-monoid-in-the-category-of-endofunctors-scala (открывать через VPN).

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

tl;dr!

Так-то можно в 2 словах сказать. У монады есть нейтральный элемент return (он же pure) и бинарная операция композиции (>=>).

return :: Monad m => a -> m a
>=> :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)

Но в Хаскеле методом инстанса вместо (>=>) является (>>=):

>>= :: Monad m => m a -> (a -> m b) -> m b

А практический совет такой: забить на наукообразные термины и смотреть по типам, что из чего получается

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

ИТОГО можно составить следующую иерархию вычислений в контексте

Functor — меняет значения, но не меняет структуру (например, fmap, примененный к списку, возвращает список той же длины)

Applicative — может менять и значения, и структуру по каким-то жестким правилам, не зависящим от того, что он меняет

Monad — может менять что хочет, как хочет (т.к. (>>=) вынимает значение из монады)

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

Но монада списка чисел определена на множестве чисел.

Вот тут ошибка. Категория — это множество и стрелки. Вот монады — это стрелки.

И на чем они определены не так важно. Они преобразуют одни элементы множества в другие, но алгебра стрелок от множества не зависит. Тут есть аналогия некоторая с операторами в функциональном анализе. Мы знаем, что ротор всякого градиента равен нулю, равно как и дивергенция всякого ротора. Ну, как бы, распиши матрицу производных, ну и получишь нуль для любого вектора, к которому мы применяем произведение операторов ротора и градиента.

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

А вот дальше из сухой теории мы должны спуститься к монаде MayBe, Apllicative и всему тому прочему. Про это мне попадалось наиболее понятное описание у Брагилевского (Vitaly Bragilevsky, Haskell in depth, Manning, 2021) и в известном сетевом учебнике «О Хаскеле по человечески».

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

множеством тут является набор стрелок

Вот здесь моё мысленное представление практического применения даёт сбой. Всё равно, что представлять вещественные числа не дробными значениями и операциями надо ними, а целыми, определёнными через числа Пеано.

Мне проще представлять, что монада контейнер (список, Maybe, IO, …) элементов (чисел, строк, списков, объектов, …), а не отображение одних функций, делающих из элемента контейнер, в другие такие функции.

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

До меня уже дошло. Я про >=> не подумал.

(>=>) тут вообще не причём. Ассоциативной операцией является natural transformation M x M -> M, то есть join.

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

А вот дальше из сухой теории мы должны спуститься к монаде MayBe, Apllicative и всему тому прочему. Про это мне попадалось наиболее понятное описание у Брагилевского (Vitaly Bragilevsky, Haskell in depth, Manning, 2021) и в известном сетевом учебнике «О Хаскеле по человечески».

Кстати, об авторе. Хотя не столько о нём, сколько о его творчестве.

Наверное самое разумное объяснение монад для «среднего программиста» которое я видел это его видео которое называется «Монады - не приговор», https://www.youtube.com/watch?v=IkXg_mjNgG4 ( Bad_ptr, и никакого бурито, зацени :) )

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

Вообще, Monad m => a -> m b — это не монада, собственно, а стрелка Клейсли (у неё тоже есть композиция, как раз (>=>) и (<=<)), но кого это волнует. А так слушай @hateyoufeel, он, наверное, больше прав.

Но вообще, ещё раз, кого это волнует. Тебе код писать или в наукообразных терминах разбираться?

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

Вот! Сбой тут возникает примерно у всех. Обратите внимание на язык FP, описанный у Филда и Харрисона (Филд, А.; Харрисон, П.: Функциональное программирование, М. Мир. 1993, pdf в сети можно найти). Язык вообще лишен свободных переменных и работает «чисто с комбинаторами». Комбинатор — это как раз пример Applicative, KMK. См. Известный Y-комбинатор рекурсии — Y f = f (Y f).

Про комбинаторы надо читать у Хаскеля (на сей раз у человека) Карри :) Он их и переоткрыл. История появления мысли о комбинаторах забавна и трагична одновременно, но это другая история.

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

яхз, у меня русскоязычная терминология этой области в голове напрочь отсутствует, а в словарь лезть лень (:

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

Практическое применение монатки, например, такое. Есть у тебя вычисление, которое может давать ошибку. Можно представить его типом Either String Result, где в строке будем хранить сообщение об ошибке. Потом, например, у тебя есть функция generateData:

loadData :: Int -> Either String Result
loadData n = if n < 0 then Left "Error" else result

Потом у тебя есть функция processData:

processData :: Result -> Either String Result
processData data = if dataGood then Right (process data) else Left "Data is not good"

Как теперь получить функцию Int -> Either String Result, которая сгенерирует данные и запустит process, если ошибок нет? А вот так: f n = loadData n >>= processData.

Вот тебе пример использования монатки

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

Или ещё одно (полу)практическое применение: сделать list comprehension в do-нотации

import Control.Monad

f :: (Ord a, Num a) => [a] -> [a]
f xs = do
  x <- xs
  guard (x > 0)
  pure $ 2 * x

f [-1, -2, 4] == [8]

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

Это как раз, когда монада контейнер (в данном случае, Either). А когда вся суть монады сводится к f n = return n >=> loadData >=> processData, как-то уже не так понятно.

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

Ассоциативной операцией является natural transformation M x M -> M, то есть join.

Как она может быть ассоциативна если (A join B) join C не равно A join (B join C)?

Да и тип у него

join :: Monad m => m (m a) -> m a

Или что есть join в Haskell?

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

Вот погодите оба. Если мы отталкиваемся от пресловутого, «монада в категории М есть моноид в категории ее эндофункторов» ,то мы должны признать, что монада — это как раз тот контейнер в котором производятся определенные действия. Вот рассмотрим пример от коллеги dura4ok11 c f [-1, -2, 4] == [8]. Ассоциативная операция тут, КМК — это последовательное применение блока do к каждому элементу массива. То есть, мы считаем, что у нас сцеплены функторы do и ассоциативная операция — это применение блока do к каждому элементу массива. Монадная операция — это сам факт применения функтора последовательно.

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

Как она может быть ассоциативна если (A join B) join C не равно A join (B join C)?

что такое A, B и C здесь?

Она ассоциативна, потому что для m (m (m a)) ты можешь сделать join в любом порядке. Здесь join . join == join . fmap join, то есть ты можешь применять join как изнутри наружу, так и снаружи внутрь. Ты просто думаешь о значениях, а тут ассоциативность работает для собственно типа m.

ghci> let x = Just (Just (Just 1))
ghci> join . join $ x
Just 1
ghci> join (fmap join x)
Just 1

Просто представь на секунду, что m (m (m a)) записывается как (m + m + m) a. Тогда это сразу станет понятнее.

@gns

Ассоциативная операция тут, КМК — это последовательное применение блока do к каждому элементу массива.

Нет. Смотри выше.

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

За 30 лет на хачкеле написали хоть что-нибудь полезное?

Cardano.

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

В каком-то смысле это и есть контейнер. Просто у него есть 2 метода: return и (>>=), подчиняющиеся специальным законам (что за законы смотри на hackage)

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

У тебя получилось выразить мою мысль точнее.

Просто представь на секунду, что m (m (m a)) записывается как (m + m + m) a. Тогда это сразу станет понятнее.

Это я и имел в виду.

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

Ты говорил о массивах каких-то. Инстансов монады куда больше, чем []. Например, State.

Всё, что нужно от монады, это написать имплементацию return и (>>=), удовлетворяющую законам монад

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

Да это пример был. Думал вслух. Как бы не очень пока всем ясен переход от ассоциативной операции в полугруппе функторов к вот этой имплементации в конкретном Хаскеле. Где тут что не есть пока очень ясно. Вот выясняем для себя.

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

Вот до сегодняшнего дня я её так и воспринимал. return = упаковать, >>= = вытащить, обработать и упаковать. Для контейнеров, для которых может не быть понятия «распаковать» (как IO).

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

Вот до сегодняшнего дня я её так и воспринимал. return = упаковать, >>= = вытащить, обработать и упаковать. Для контейнеров, для которых может не быть понятия «распаковать» (как IO).

Нуууу… всё, конечно, так, но не совсем. Например, Proxy из Data.Proxy – имеет instance Monad, но он ничего не хранит, потому что

data Proxy a = Proxy

instance Functor Proxy where
  fmap f Proxy = Proxy

instance Applicative Proxy where
  Proxy <*> Proxy = Proxy
  pure _ = Proxy

instance Monad Proxy where
  Proxy >>= f = Proxy

Так себе контейнер. Есть и более интересные типы, которые имеют такие инстансы, но тоже не особо хранят какие-то значения.

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

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

AndreyKl ★★★★★
()

Монады и категории — эт' всё, конечно, хорошо... А вот с этим что делать?

Получается, что то ли я дурак, то ли жопа через два П пишется, то ли... Зря они все это затеяли что ли с фиксацией набора версий пакетов внутри кабала/стека/ghcup'a?

gleb@raccoon:~/src/matterhorn$ cabal new-build -j --enable-tests --minimize-conflict-set
Resolving dependencies...
Error: [Cabal-7107]
Could not resolve dependencies:
[__0] trying: matterhorn-90000.0.1 (user goal)
[__1] trying: vty-crossplatform-0.4.0.0 (dependency of matterhorn)
[__2] trying: vty-unix-0.2.0.0 (dependency of vty-crossplatform)
[__3] trying: microlens-th-0.4.3.16 (dependency of vty-unix)
[__4] trying: template-haskell-2.21.0.0/installed-f842 (dependency of microlens-th)
[__5] trying: pretty-1.1.3.6/installed-c96a (dependency of template-haskell)
[__6] next goal: data-clist (dependency of matterhorn)
[__6] rejecting: data-clist-0.2 (conflict: matterhorn => data-clist>=0.1.2 && <0.2)
[__6] rejecting: data-clist; 0.1.2.3, 0.1.2.2, 0.1.2.1, 0.1.2.0 (conflict: pretty => deepseq==1.5.0.0/installed-adea, data-clist => deepseq>=1.1 && <1.5)
[__6] rejecting: data-clist-0.1.1.0 (conflict: matterhorn => data-clist>=0.1.2 && <0.2)
[__6] skipping: data-clist; 0.1.0.0, 0.0.7.4, 0.0.7.3, 0.0.7.2, 0.0.7.1, 0.0.7, 0.0.6, 0.0.5, 0.0.4, 0.0.3, 0.0.2, 0.0.1 (has the same characteristics that caused the previous version to fail: excluded by constraint '>=0.1.2 && <0.2' from 'matterhorn')
[__6] fail (backjumping, conflict set: data-clist, matterhorn, pretty)
After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: template-haskell, pretty, data-clist, microlens-th, matterhorn, vty-unix, vty-crossplatform

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

Используй stack. Но вообще, очевидно, у тебя [__6] rejecting: data-clist-0.2 (conflict: matterhorn => data-clist>=0.1.2 && <0.2) верхняя версия зависимости прописана. Убери её либо поставь версию повыше. Либо добавь флаг –allow-newer кабалу.

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

Ладно, вот тебе такой пример.

data Void1 a

instance Functor Void1 where
  fmap _ _ = error "Void cannot be constructed"

instance Applicative Void1 where ...
instance Monad Void1 where ...

Это точно совсем не контейнер.

hateyoufeel ★★★★★
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.