Andrei
кстати фейсбук нанимает людей пилить GHC
Alexander
учитывая они берут человека в год, шансов попасть мало
Alexander
я попал в четверку лучших кандидатов тогда
Vladislav
Alexander
у них самое классное интервью было из всех на которых я был
Aleksei (astynax)
Фейсбук ковровые бомбардировки устраивает походу - мне и в Linkedin написали и на почту (рекрутер какой-то) и на реддите вакансия
Vladislav
@qnikst А в этом году не хотите попробоваться?
Tuesday, 27 March 2018
Два месяца назад вакансия была.
Alexander
нет :)
Vladislav
Alexander
меня работа в Tweag устраивает более-менее
Alexander
оно по irc :)
Alexander
весьма интересная атмосфера
Alexander
и задачка очень неожиданная, но подробности говорить не буду, т.к. они похоже не сильно её меняют
Alexander
задачку - по ssh подключиться и разобраться в чем проблема и если получится поправить, причем програмка очень маленькая
Leonid 🦇
это даже мрачнее чем whiteboard
Alexander
да ну, вообще класс
Andrei
Ilya
Вопрос по линзам. Как-то можно пройтись по всем сеттерам структуры, чтобы над каждым выполнить какое-то действие?
То есть для вот такой структуры
data Crowd a = Crowd {_first :: a, _second :: a, _third :: a} deriving Show
makeLenses ''Crowd
Я хочу поработать с чем-то типа Crowd (Lens' (Crowd a) a), то есть сразу со всеми сеттерами.
Вот минимальный пример, зачем это может понадобиться:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
import Control.Lens
data Crowd a = Crowd {_first :: a, _second :: a, _third :: a} deriving Show
makeLenses ''Crowd
new :: Int -> Crowd Int -> Crowd (Crowd Int)
new x c = Crowd {_first = set first x c,
_second = set second x c,
_third = set third x c}
Хочется функцию new написать по-нормальному, не используя внутреннюю реализацию типа Crowd.
@kana_sama
кана
... deriving Functor
fmap
Ilya
Alexander
(const x)
кана
{-# LANGUAGE DerivingFunctor #-}
data Crowd a = Crowd
{ _first :: a
, _second :: a
, _third :: a
} deriving (Show, Functor)
makeLenses ''Crowd
new :: Int -> Crowd Int -> Crowd Int
new x = fmap (const x)
Ilya
я имею в виду контейнер какой
кана
а
кана
я увидел
Alexander
это уже Co* какие-то
кана
в каждом поле поле у тебя копия Crowd с только этим изменным полем
кана
да, выглядит как комонада какая-то
Alexander
угу
Ilya
кана
ну все же не думаю, что в линзах есть что-то, что отдает список линз или линзу текущего поля во время траверса или что-то подобное
кана
с generic такое написать можно наверное
Alexander
я бы не парился и написал руками
Сергей
uniplate стоит попробовать
кана
fields :: [Lens (Crowd a) a]
fields = [first, second, third]
new x c = map (\field -> set field x c) fields
Ilya
я бы не парился и написал руками
руками не проблема написать, но позже тип Crowd будет не конкретный, в виде data Crowd :: * -> * (data family). А реализация new всё равно должна быть.
*Правда я ещё не разбирался с data family, но вроде это как раз то что нужно
Ilya
Alexander
тогда generic надо
Alexander
а не линзы
Ilya
generic-lens?
Alexander
просто свой класс с generic
Alexander
линзы зачем тут тебе?
Alexander
который делаеть new :: Generic f => a -> f a -> f (f a)
Alexander
зачем тебе set?
Ilya
Alexander
в общем самый простой способ - сделать класс:
class Duplicate f where
dup :: a -> f a -> [f a]
Alexander
написал для кого надо руками, а потом сделать generic реализацию
Alexander
хм.. с generic-lens наверное тоже можно
A64m
лучше бы желающие изучить хаскель вместо теорката изучали его имплементацию, теребили бы всякие игрушечные стг-интерпретаторы
хоть понимали бы как ленивость работает
A64m
я не понял задачу про линзы
Alexander
блин f (f a) выше конечно же
Ilya
зачем тебе set?
set мне понадобился в функции forget. Вот код:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
import Control.Lens
data Crowd a = Crowd {_first :: a, _second :: a, _third :: a} deriving Show
makeLenses ''Crowd
type Man = forall a. Lens' (Crowd a) a
new :: Int -> Crowd Int -> Crowd (Crowd Int)
new x c = Crowd {_first = set first x c,
_second = set second x c,
_third = set third x c}
forget :: (Enum a, Bounded a) => Man -> Crowd a -> [Crowd a]
forget man c = [set man x c | x <- [minBound .. maxBound]]
Пример работы:
λ> forget first (Crowd True True True)
[Crowd {_first = False, _second = True, _third = True},Crowd {_first = True, _second = True, _third = True}]
Функция new более сложная, и там внутри должен использоваться forget
Alexander
я не понимаю смысла forget
Leonid 🦇
https://www.youtube.com/watch?v=a7R-2vtPLDM
комитетчики осваивают медийное пространство для ведения войны
Alexander
и не вижу зачем там set прям обязательно
Ilya
я не понимаю смысла forget
он забывает конкретное значение поля, и возвращает все возможные конфигурации, где вместо этого поля любой из возможных вариантов. А остальные не меняются
Alexander
c{man=_x} - и нету линз и сета
Сергей
Alexander
не похоже, оно же должно знать в каком оно поле
Alexander
от этого поведение меняется
Сергей
По типу в любом месте структуры траверсит
Alexander
а man там это линза, ок
Alexander
он контекст же не хранит
Alexander
тут поведелие зависит от положения в структуре
Сергей
Тогда, да
Alexander
мы меняем первое поле, то в генеремом значении мы должны менять первое поле
A64m
очень часто в контексте изучения хаскель слышу про вот какую-то особенную особенность ленивости в хаскеле. детали не копал особо, но лишь понимаю сам принцип, в традиционном изложении: мол до тех пор пока какой-то expression не нужен, он не будет вычислен. т.е. своего рода pull model.
из совета постижения стг-интепретатора и ленивости, что конкретно стоит изучить ? какой конкретно аспект этой ленивости ? т.к. сейчас это кажется каким-то вроде как понятным, но раз часто так упоминают, то вероятно есть что-то мудреное там.
да там нет ничего "мудреного" как такового, да, примерно как описали так и есть, надо просто привыкнуть думать о вычислениях что они именно так происходят, пограть с каким-нибудь вычислителям вроде этого
https://www.well-typed.com/blog/2017/09/visualize-cbn/
или
stgi
https://hackage.haskell.org/package/stgi
https://skillsmatter.com/skillscasts/8800-functional-and-low-level-watching-the-stg-execute
Ilya
set мне понадобился в функции forget. Вот код:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
import Control.Lens
data Crowd a = Crowd {_first :: a, _second :: a, _third :: a} deriving Show
makeLenses ''Crowd
type Man = forall a. Lens' (Crowd a) a
new :: Int -> Crowd Int -> Crowd (Crowd Int)
new x c = Crowd {_first = set first x c,
_second = set second x c,
_third = set third x c}
forget :: (Enum a, Bounded a) => Man -> Crowd a -> [Crowd a]
forget man c = [set man x c | x <- [minBound .. maxBound]]
Пример работы:
λ> forget first (Crowd True True True)
[Crowd {_first = False, _second = True, _third = True},Crowd {_first = True, _second = True, _third = True}]
Функция new более сложная, и там внутри должен использоваться forget
вот код. он работает. нужно переписать new так, чтобы она не использовала знание о внутренней структуре типа 'Crowd`. Для этого я пытаюсь использовать линзы. Есть пример одной функции, уже реализованной "как нужно" — функция forget. В таком же духе хочется переписать и new.
кана
ну вот duplicate через generic это то что нужно
кана
без линз даже
Alexander
мне тут подсказали context в plated линзах
Alexander
может поможет
Alexander
очень часто в контексте изучения хаскель слышу про вот какую-то особенную особенность ленивости в хаскеле. детали не копал особо, но лишь понимаю сам принцип, в традиционном изложении: мол до тех пор пока какой-то expression не нужен, он не будет вычислен. т.е. своего рода pull model.
из совета постижения стг-интепретатора и ленивости, что конкретно стоит изучить ? какой конкретно аспект этой ленивости ? т.к. сейчас это кажется каким-то вроде как понятным, но раз часто так упоминают, то вероятно есть что-то мудреное там.
С ленивостью все и просто, и сложно одновременно. По началу можно ограничиться тем, что ленивость позволяет преобразовывать структуры без немедленного обхода их целиком. Напиши, например, функцию для создания графа: она принимает вершину и возвращает список смежных вершин. Одна такая функция будет полным описанием графа. Напиши теперь другую функцию, которая, используя первую, преобразует граф в список смежности. И вот пока ты работаешь с первыми элементами этого списка, он весь не вычисляется. Может, по задаче вообще не надо будет.
Dmitry
Alexander
а если бы меня слушали уже бы все знали !!!