Ilya
вообще меня радует что есть уже две с половиной попытки пойти в сторону компиляции хаскеля в васм. это движение в верную сторону, когда-нибудь количество перейдет в качество. Ещё в январе на горизонте вообще ничего не было
A64m
так имплементировать ленивые языки вообще сильно сложнее чем строгие, конечно для идриса или там пурскрипта должно быть легче сделать бекенд
A64m
не, webghc это прошлогодний hsoc
Ilya
да, в том числе понимание этих нюансов особенно отчетливо после идриса пришло
A64m
т.е. про такой проект уже год известно
Ilya
я его не нашел когда ресёрчил кстати 🙂
Ilya
а так в идрисе тоже есть ленивость, впринципе можно для всех типов дописать Lazy и будет вполне себе хаскель
Ilya
правда код в этом случае не самый эффективный сгенерится
A64m
нету, или не было до недавнего времени, по крайней мере
A64m
там Lazy не кеширует результат вычисления
Ilya
тоже правда
A64m
так что там не то что неэффективность - будет другая асимптотика
A64m
тем временем поиск подстановок в дырки успел в 8.6 https://github.com/ghc/ghc/commit/e0b44e2eccd4053852b6c4c3de75a714301ec080
A64m
не языковая фича, но интересная
Евгений
там Lazy не кеширует результат вычисления
То есть Lazy это на самом деле call-by-name?
A64m
да, в районе первой версии когда я мультиленгвидж фп-бенчмарк делал так было, сейчас может поменялось, не знаю
Anonymous
Зигоморфизм — генерализация параморфизма, которая повзволяет фолдить структуру с помощью вспомогательной функции zygo :: Functor f => Algebra f b -> (f (a, b) -> a) {- следовало бы и здесь алгебру определить -} -> Mu f -> a zygo f g = fst . cata (g &&& f . fmap snd) Препроморфизм — катаморфизм с дополнительным естественным преобразованием, которое применяется перед интерпретацией через представленную Ф-алгебру на каждой итерации рекурсивной процедуры prepro g f = f . (fmap . prepro . cata (Mu . g)) f . out Постпроморфизм — корекурсивная схема, являющаяся дуализмом к препроморфизму, позволяющая с помощью соответствующего естественного преобразования генерировать коданные. Постпроморфизм можно представить в виде генератора. К примеру функция вычисления факториала на питоне с помощью генератора будет выглядеть примерно так def fac(a): n, f = 0, 1 while n < a: n, f = n + 1, f * (n + 1) yield f На хаскелле с использованием постпроморфизма fac = flip postpro stream . phi where stream = Cons <*> succ phi _ Nil = Nil phi n alg@(Cons a b) | a <= n = alg | otherwise = Nil Хистоморфизм — генерализация катаморфизма на косвободной комонаде, изменяющий форму фолд, сохраняющий всю историю значений во время рекурсивной процедуры, нежели чем самый последний элемент. Основное применение хистоморфизма используется для мемоизации. histo :: Functor f => CVAlgebra f a -> Mu f -> a histo f = out >>> fmap phi >>> f where phi t = (Cofree . Mu .: CoBindF) (histo f t) ((out t) <&> uncofree . phi) Футуморфизм — дуализм к хистоморфизму, ана на свободной монаде, конструирует Ф-алгебраическую структуру пошагово где коалгебра может вернуть несколько уровней подструктуры одновременно futu :: Functor f => CVCoalgebra f a -> a -> Mu f futu f = Mu <<< fmap phi <<< f where phi (Free(Mu(ReturnF a))) = futu f a phi (Free(Mu(BindF a))) = (Mu .: fmap) phi a) * Следует также прочесть cs.ox.ac.uk/people/daniel.james/sorting/sorting.pdf cs.ox.ac.uk/people/nicolas.wu/publications/Histomorphisms.pdf cs.cornell.edu/~jeannin/papers/wf.pdf citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.41.125&rep=rep1&type=pdf † Элгот алгебры iti.cs.tu-bs.de/~milius/research/elgot_lmcs.pdf comonad.com/reader/2008/elgot-coalgebras ‡ Насчёт имплементации по Мендлеру researchgate.net/publication/244249998_Coding_Recursion_a_la_Mendler_Extended_Abstract researchgate.net/publication/220370687_The_Recursion_Scheme_from_the_Cofree_Recursive_Comonad Продолжение следует
Статья на эту же тему, правда? https://jtobin.io/time-traveling-recursion
Dmitry
import Data.List (unfoldr) f :: [a] -> [(a, a)] f = unfoldr $ \case x:y:ys -> Just ((x, y), ys) _ -> Nothing
go :: [a] -> [(a, a)] go (x:y:zs) = (x, y) : go zs go _ = [] Хоть понятнее ;)
Aleksei (astynax)
Dmitry
Нуу, c или basic в качестве имени функции как-то странно использовать. Вот go -- самое то!
Aleksei (astynax)
Вот чтобы не придумывать ненужные имена, анонимные функции и существуют :) Для такой тривиальной задачи точно стоит unfoldr использовать, а не руками рекурсию писать.
Aleksei (astynax)
А go можно оставить для тех случаев, когда размер функции довольно большой :)
Sr
А тут целых три!
Sr
Ладно две, но не одна ведь!
Sr
Можно и в одну, но опять же вызвать отдельно придётся
Sr
А там где объявил там и заюзал
Ю ли я? 🤔
А нет ли бесконечного unfold, чтобы в Just всегда не заворачивать? Нахуглить не удалось.
Dmitrii
А нет ли бесконечного unfold, чтобы в Just всегда не заворачивать? Нахуглить не удалось.
Возможно, просто iterate хватит. Но, наверное, проще будет такой бесконечный unfold самому реализовать.
Dmitry
Можно и в одну, но опять же вызвать отдельно придётся
Ну тогда так: go x = (init . map (\[a,b] -> (a,b)) . chunksOf 2) (x ++ [undefined])
Dmitry
Достаточно однолинейно?
Sr
Ох ну ты и завернул)
Dmitry
Интересно, как бесточечно \[a,b] -> (a,b) сделать? У меня pointfree отказывается
Sr
Там будет много head tail и оно не нужно
Dmitrii
Ну тогда так: go x = (init . map (\[a,b] -> (a,b)) . chunksOf 2) (x ++ [undefined])
Правда, это решение падает с исключением на списках нечетной длины, если только не писать свой exactChunksOf.
Sr
Должно сработать
Sr
@dmalkr я тебе бесточечный стиль подогнал
Sr
(,) <$> head <*> (head . tail) :)
Мне кажется у меня проще
Dmitry
Ox...
Зато в одну строчку ;))
Sr
(,) <$> head <*> (head . tail) :)
И почему drop 1 а не tail?
Aleksei (astynax)
да. tail, конечно
IC
Что лучше - абьюз операторов из стрелок или абьюз инстанса для (-> а)?
Aleksei (astynax)
ну инстанс для (-> a) в таком случае как раз к месту
IC
(ответ: написать по человечьи, с именами, без вот этого всего)
Sr
Что лучше - абьюз операторов из стрелок или абьюз инстанса для (-> а)?
Лучше как уже много раз сказали запилить норм функцию и не выдаваться, но эт не про нас)
Aleksei (astynax)
Это же как раз "применяем несколько функций к одному аргументы и компонуем результаты другой функцией" - идеальный случай для Applicative (-> a)
Anatolii
(ответ: написать по человечьи, с именами, без вот этого всего)
Мы зачем на хаскеле пишем? Конечно чтобы поинтфри впиливать где можно или нельзя 🤣
IC
Мы зачем на хаскеле пишем? Конечно чтобы поинтфри впиливать где можно или нельзя 🤣
Не знаю зачем пишете вы, но нам друг за другом приходится ещё и код поддерживать.
Alexander
У iterate тип не тот, только если ещё с map поверх.
ещё раз повторюсь, что тип Stream для этого. Развертка которая не может получить все значения структуры не нужна
Ю ли я? 🤔
В смысле - все значения структуры?
Alexander
в прямом
Alexander
желаемый unfold не покрывает все возможные списки
Alexander
так что Stream.toList . Stream.unfold
Ю ли я? 🤔
Anatolii
Не знаю зачем пишете вы, но нам друг за другом приходится ещё и код поддерживать.
Ну шучу конечно же, я сам постоянно сам себя по рукам бью когда заигрываюсь
Ю ли я? 🤔
Ну или там enumFrom
Alexander
Чем он хуже iterate в таком плане?
тем что iterate не соотносится ни с какой алгебраической структурой со своими свойствами
Ilya
Чем он хуже iterate в таком плане?
хотеть unfoldr, который даёт только бесконечные списки это то же самое, что хотеть foldr, который принимает только бесконечные списки (т.е. ему не нужен второй аргумент)
Ilya
тут @qnikst прав полностью
Kirill
а на хаскеле же не подвозили никакой дистрибутед-тестилки аля mzbench?
Dmitry
Mzbench был немножко на хаскеле в один момент
Dmitry
Но потом начальство сказало «отказать»
A64m
А что за бенчмарк?
псевдорешето псевдотернера на всех ФЯ
Kirill
@qni
Kirill
@qnikst а вы какие-нибудь такие большие тесты делаете? если да, то чем?
Alexander
смотря чего, или интеграционные клиентами
Alexander
для ch был пакет distributed-commands который на всех хостах запускает управлялку и роутит нужные события и логи в центр
Alexander
их там процессим и проверяем прошел ли течин