Vasiliy
docker совсем не zerocost
Vasiliy
а в своём скрипте я использую https://hackage.haskell.org/package/linux-namespaces-0.1.2.0
Alexander
в 8.2.3 вроде пофиксили?
Alexander
наверное не стоит
Anonymous
Хорошо ли так писать: someFunc x= do ••• someFunc y
Anonymous
?
кана
Ну это обычная рекурсия, почему нет
кана
Но часто (или всегда) рекурсию можно заменить свертку/развертку
Alexander
так хорошо, а вот так, скорее всего не очень: someFunc x = (z +) <$> someFunc y
parket
Хаскель не мемоизирует из коробки? double f a = f a + f a f a будет выполнен дважды, верно?
Cheese
> Хаскель не мемоизирует из коробки? да > double f a = f a + f a > f a будет выполнен дважды, верно? нет
parket
Неожиданный ответ. А почему так?
Cheese
благодаря equational reasoning компилятор может переписать в double f a = fa + fa where fa = f a
parket
Может, или перепишет? :)
Cheese
это оптимизация
Cheese
есть много вещей, мешающих компилятору применить оптимизацию
Cheese
если ничего не помешает, то перепишет
parket
Понял. Вопрос в общем то был про fix. fix f = f $ fix f fix $ \a -> (4, fst a) -- (4,4) Поведение логично, но, сколько раз будет выполнена лямбда.
Зигохистоморфный
join (+) $! (f a) можно как-то так
Cheese
join (+) $! (f a) можно как-то так
можно, но зачем делать грязную работу вместо компьютера?
Зигохистоморфный
чтобы понимать bang =)
Кабачок
А если туда trace бахнуть?
Зигохистоморфный
а если просто руками бета редукцию на бумажке написать?
Cheese
А если туда trace бахнуть?
тогда ответ сразу увидишь, скучно
parket
а если просто руками бета редукцию на бумажке написать?
Если руками, то 2. (4, fst $ fix ...) -> (4, fst (4, fst $ fix ...)) -> (4, 4)
Зигохистоморфный
лучше всего понимать на лямбде (основа для Y комбинатор) (\x -> x x)(\x -> x x) :D
parket
fix $ \a -> trace "Alle Ap" (4, fst a) -- Output: -- Alle Ap (4,Alle Ap 4)
parket
Таки 2.
parket
И теперь мы плавно переходим в MonadFix. Почему это вообще работает. В частности mdo.
Cheese
Зигохистоморфный
это понятно) но никто не мешает выразить fix даже через рекурсивные схемы
Alexander
Prelude Data.Function> :m +Debug.Trace Prelude Data.Function Debug.Trace> fix (\a -> trace "A" (4, fst a)) A (4,4)
Alexander
fix :: (a -> a) -> a fix f = let x = f x in x
Alexander
в этом случае явно есть мемоизация и шаринг
parket
Понятно. Т.е. мой наивный фикс делает редукцию дважды.
Alexander
в случае с fix f = f $ fix f - нет
Alexander
да
parket
Так. Хорошо. Самое интересное, для меня: mfix :: (a -> ma) -> ma
parket
Он же производит join контекстов?
Alexander
почему оно работает или что?
parket
Чисто игрушка. Работать не будет. Но такова ли суть? mfix mf = mfix mf >>= mf
parket
Где mf :: a -> ma
Зигохистоморфный
считай что mfix это fix но только еще может применять эффекты
Зигохистоморфный
лучше начать смотреть на cata и потом на cataM (все эти fix лучше через рекурсивные схемы и алгебры надо понимать)
parket
Да, вот есть у нас 2 фикса fix f = f $ fix f fix f = let x = f x in x Первый вызывает нашу игрушечную функцию дважды Для mfix это будет критично, т.к. join контекстов.
parket
Суть вопроса, понять mdo
Alexander
для Monad должно быть MonadFix инстанс
parket
Как этот сахарок развернуть
Alexander
через mfix :: MonadFix m => (a -> m a) -> m a
parket
для Monad должно быть MonadFix инстанс
Т.е. мы там определяем mfix без join-а контекстов?
Alexander
так давай на примере, что ты хочешь в mdo запустить?
parket
А нет примера. Что-то. В общем хочу понять
Зигохистоморфный
обкурются своим теоркатом...
ну почему) решение через алгебры всегда более законно =)
parket
обкурются своим теоркатом...
Полезная штука. Я бы тоже обкурился. Но как-то очень медленно. И уровень мягко говоря очень поверхностный.
Alexander
ну ладно mdo { tid <- forkIO $ use ref ; ref <- (Ref tid); return ref } подойдет?
parket
Судя по всему, мы таки отбрасывем контекст. и mfix это не mfix mf = mfix mf >>= mf а скорее mfix mf = mf $ unwrapAndDropContext $ mfix mf
Alexander
оно дешурагится в:
Alexander
mfix (\ref' -> forkIO (use ref') >>= \tid -> return (Ref tid) >>= return
Alexander
+-
Alexander
mfix (return. h) = return (fix h) mfix ('\x.a >>= ! x) = a >>= \y.mfix ('\x.! x y) mfix ('\-(x, _).mfix ('\-(-, y).f (x, y))) = mfix f Figure 1: Axioms for mfix. In axiom 2, x is not free in a
Alexander
https://digitalcommons.ohsu.edu/cgi/viewcontent.cgi?httpsredir=1&article=1060&context=csetech <- статья с подробностями
Alexander
{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE RankNTypes #-} data Key s = Key Int data W a s = W a data VK a = forall s. VK (W a s, Key s) doom :: a -> Int -> IO (VK a) doom a i = pure $ VK (W a, Key 0) redoom :: W a s -> Key s -> IO (VK a) redoom a k = pure $ VK (a, k) free :: W a s -> Key s -> IO () free _ (Key i) = print ("free", i) test :: IO (VK (IO ())) test = do vk1 <- doom (putStrLn "5") 0 vk2 <- doom (putStrLn "6") 1 case vk1 of VK (a1, k1) -> case vk2 of VK (a2, k2) -> do free a1 k1 -- fro a2 k1 --fails free a2 k2 -- fro a2 k2 --fails redoom a1 k1
Alexander
это как-нить более человечески сделать можно?
кана
Если бы понять, что такое W и VK. Ну, что сами имена раскрывают
Alexander
ничего, буквы удобные // ладно VK - Value Key
Alexander
идея - вернуть, упакованое значение и его ключ, так чтобы в free можно было положить значение вместе со своим ключем
Alexander
в предположении, что конструктор W не экспортируется, а экспортируется только withW :: оно даже имеет шанс на то, что будет работать
Leonid 🦇
https://www.reddit.com/r/programming/comments/7ctwi7/yaml_sucks/ @cblp_su хайпанем немножко?
Cheese
да ладно!
Aleksei (astynax)
Добавь пример с &/*
Aleksei (astynax)
_foo: &baz foo: bar bar: baz qux: <<: *baz doo: doh
Cheese
Добавь пример с &/*
пулреквестируйте
Aleksei (astynax)
Оке
Cheese
Добавь пример с &/*
а разве он покажет что-то, отличное от примеров с <<?
Aleksei (astynax)
Тут важно проверить, что реально иклюдится
Aleksei (astynax)
Питон и хаскель нормально инклюдят
Aleksei (astynax)
rq -y -J < foo.yaml { "_foo": { "bar": "baz", "foo": "bar" }, "qux": { "<<": { "bar": "baz", "foo": "bar" }, "doo": "doh" } }