Ilya
Спасибо
Пиши в чат, если не получится. И какая свёртка кстати, линейная или циклическая?
Alexander
new :: (Hashable a, Ord a) => Config -> IO (Cache a b) new Config{..} = do ref <- newIORef PSQ.empty pure $ Cache { requestOrInternal = \tm k f -> mdo mbox <- atomicModifyIORef ref $ swap . PSQ.alter (\case Just (p,~v) | p >= tm ^-^ cacheLongestAge -> (Just v, Just (tm, v)) _ -> (Nothing, Just (tm, Lazy result))) k result <- maybe (trace "f" $ f k) (evaluate . getLazy) mbox atomicModifyIORef ref $ swap . PSQ.alterMin (\case Nothing -> ((), Nothing) Just (kk,p,v) | p < tm ^-^ cacheLongestAge -> ((), Nothing) | otherwise -> ((), Just (kk,p,v)) ) pure result }
Alexander
так сработало
Leonid 🦇
^-^ - найс
Alexander
но добавление Lazy и getLazy не очевидно
Alexander
из бонусов, что неявный лок на вызове evaluate . getLazy
Alexander
т.е. только 1 тред будет работу работать
Alexander
я очень люблю эту фишку, но я боюсь, что это accidental complexity
Alexander
с другой стороны если не это, то мне бы сложные вещи пришлось бы переизобретать
Aleksei (astynax)
^-^ - найс
оператор "котик спрятался, видно только ушки"
Leonid 🦇
оператор nya
кана
а можно ли в семействах добавлять новые типопеременные?
Leonid 🦇
оператор "котик спрятался, видно только ушки"
хотя я думал так в аниме радость изображают
Aleksei (astynax)
И это тоже. Псто я предложил менее виабушный вариант
кана
f :: HasField "a" r0 r1 String Int => HasField "b" r1 r2 Int String => Record r0 -> Record r2 вот имею такой код, хочу написать хелпер для композиции HasField, но для этого придется скрыть из внешнего скоупа r1 и добавить в скоуп внутри семейства, это реально?
кана
type family RecordDelta fs r0 rn :: Constraint where RecordDelta '[] r r = () RecordDelta ('(name, a -> b) ': fs) r0 rn = forall r1. (HasField name r0 r1 a b, RecordDelta fs r1 rn) типа такого
Cheese
а это всего-лишь AdditiveGroup
чем аддитивная группа отличается от группы? только тем, что входит в иерархию классов?
Евгений
Обычно сложением называют коммутативную операцию
Cheese
Обычно сложением называют коммутативную операцию
обычно коммутативную группу называют коммутативной или абелевой
Alexander
википедия ссылаясь на "Каргаполов М. И., Мерзляков Ю.И. Основы теории групп. — 3-е изд.. — Москва: Наука, 1982. — С. 18. — 288 с. — 11 800 экз." использует аддитивная
Alexander
но вообще это класс из vector-space пакета
Alexander
и я не знаю что и как принято называть там откуда родом автор пакета
Cheese
ещё в Хаскеле иногда нужна просто полурешётка, а иногда отдельно верхняя и нижняя. и эти классы никак друг с другом не связать. печалька
Alexander
в numeric-prelude достаточно большая иерархия
Alexander
но полурешеток вроде нету
Cheese
раздельные есть в lattices
Cheese
простую я сам изобретал
Alexander
фигово, что нельзя простым образом добавить в base
Alexander
т.к. сложность бешено быстро растет
Alexander
сложность программирования
Алексей
Что именно? Более вменяемые классы для чисел?
Alexander
ага
Alexander
ну вообще всю эту алгебру честную бы засунуть
Alexander
у нас только vector-space и numeric-prelude как эксперименты
Алексей
Ну хотя бы выдрать аддитивную группу и кольцо из Num
Alexander
может возможнен промежуточный вариант, достать все честные структуры
Алексей
Ну хотя бы аддитивную группу
Cheese
и fromInteger отделить как синтаксический костыль
Alexander
и в transition period сделать Num зависяшим от себя
Alexander
да-да-да
Alexander
реально бесит
Алексей
Всех — слишком много. Выходит по классу на операцию :( С одной стороны так и надо, с другой — морочно
Alexander
ну т.е. будет промежуточный вариант, хочешь - используешь, не хочешь берёшь Int/Double где все есть
Alexander
о кметтопакет
саша
Вопрос, а почему я в рамках ду нотации часто вижу pure вместо return? Экономия на символах?
A64m
некоторые считают такой подход более принципиальнм
A64m
return - это реликт со времен, когда Monad и Applicative не были в одной иерархии
Cheese
у меня получилась такая иерархия class CFoo a where foo :: TFoo class CFoo a => CFooBar a where foobar :: TFooBar class CFoo a => CFooBaz a where foobaz :: TFooBaz fooViaBar :: TFooBar -> TFoo fooViaBaz :: TFooBaz -> TFoo data X instance CFoo X where foo = fooViaBar instance CFooBar X where foobar = (realImplementation) data Y instance CFoo Y where foo = fooViaBaz instance CFooBaz Y where foobaz = (realImplementation) чувствую, что-то не так, но не могу понять как правильно. что посоветуете?
Alexander
некоторые считают что return путает людей
Alexander
и.к. это не ретурн из императивных яп
Aleksei (astynax)
"pure - для аппликативных выражений, return - для do-блоков" :)
Алексей
Нужны классы-синонимы. Тогда развесистые иерархии не страшны и можно дробить тайпкласссы. Что-то вроде class Functor a => Applicative a = Pointed a, Apply a class Pointed ... class Apply ... Можно объявлять инстансы по отдельности, а можно вместе. instance Applicative даёт инстансы Pointed и Apply, инстансы Pointed и Apply дают Applicative
Алексей
Гранулярная иерархия становится нестрашной
Cheese
type Applicative a = (Functor a, Pointed a, Apply a)?
Алексей
Да, плюс сахар для объявления инстансов
Алексей
instance Applicative f where pure = ... (<*>) = ... рассахаривается в instance Pointed f where pure = ... instance Apply f where (<*>) = ...
Cheese
Да, плюс сахар для объявления инстансов
а, это про алгебру, не про мой вопрос?
Алексей
Это про страдания с классами.
Алексей
Тредов нет
Алексей
всё вперемешку
Alexander
а ещё можно Old.Applicative
Alexander
+ deriving via
Алексей
Просто в этом случае мы автоматически получаем инстансы для Pointed и Apply. Для всех типов, где есть Applicative
Alexander
но с дерайвинг в другую сторону не будет
Алексей
А тут в обе стороны
Алексей
Основная идея тут сделать возможным дробление тайпкласссов
Cheese
если менять язык, то можно создавать автоматические классы из функций. правда, все сразу начнут создавать мультиметоды — беззаконные классы
Cheese
classy (+) :: a -> a -> a instance (+) :: Int -> Int -> Int where ....
Алексей
Автоматические классы?
Алексей
Это уже что-то нездоровое, кмк