A64m
да
Alexander
Вы бы видели что в JS называют фп
Vladislav
в ФП чатах тоже решить что такое ФП не могут
A64m
ладно, раз тут @int_index появился надо повторить вопрос
A64m
допустим, мы хотим выбирать тайпкласс в месте использования функции
Alexander
Vladislav
интересное начало, а как мы его выбираем?
Vladislav
и до того как мы его выбрали, то как код пишется, если он не знает, из какого класса ему тёрмы доступны?
A64m
мы выбираем указанием ньютайпа, для которого имплементирован тот инстанс, который нам нужен
A64m
после чего кастим функцию к тому типу, который нужен в месте использования
A64m
вопрос в том, как это сделать с минимальными аннотациями типов
Vladislav
если я правильно понял, то нам дано
class Foo a where
foo :: ...
instance Foo A
instance Foo B
class Bar x where
bar :: ...
instance Bar X
instance Bar Y
и мы хотим Quux a, который дает метод quux, где quux = foo для A и B, и quux = bar для X и Y?
Leonid 🦇
Вот да https://www.reddit.com/r/haskell/comments/8ilw75/there_are_too_many_prettyprinting_libraries/
A64m
что мы точно можем:
> foo :: Ord a => ([Down a] -> [Down a]) -> [a] -> [a]; foo = coerce
> foo sort [1..10]
[10,9,8,7,6,5,4,3,2,1]
что хотелось бы получить
> (sort @@ Down) [1..10]
[10,9,8,7,6,5,4,3,2,1]
вопрос в том, насколько мы можем продвинутся из пункта А в пункт Б
A64m
@int_index ^
Vladislav
Я не понял где тут "выбирать тайпкласс", работаем только с Ord
A64m
инстанс
Vladislav
import Data.Coerce
(@@) :: (Ord b, Coercible a b) => ([b] -> [b]) -> (a -> b) -> ([a] -> [a])
(@@) f _ = coerce f
*Main Data.List Data.Ord> (sort @@ Down) [1,2,3]
[3,2,1]
Vladislav
Вот так что ли?
A64m
это должно работать не только для sort
A64m
тут есть два пути добавления большего числа аннотаций, как я понимаю
1) описывать "структуру" того, что мы кастим т.е.
(sort @@ map Down) [1..10]
2) конкретные типы и семейства типов, которые конструируют "обернутый" тип
(foo @Int @Down sort) [1..10::Int]
что не весело совсем
Anonymous
Что делает >>=
Можно примеры?
Andrew
Andrew
(>>=) :: m a -> (a -> m b) -> m b
Leonid 🦇
ну наконец-то начали ругать https://gist.github.com/chexxor/23ccf35add7dbdd33ecdd26888663140
Cheese
A64m
> [1..5] >>= (:[])
[1,2,3,4,5]
Зигохистоморфный
A64m
или может для конкретных но с меньшими аннотациями в месте использования
Cheese
Cheese
а, там предыстория выше
Vladislav
Скорее такое
type family Modify (a :: k1) (b :: k2) (f :: k3) :: k3 where
Modify a b a = b
Modify a b (f x) = (Modify a b f) (Modify a b x)
Vladislav
Но я не знаю как от аннотаций избавляться
Vladislav
Хм, оно еще не редьюсится почему-то
Vladislav
*Main Data.List Data.Ord> :kind! Modify Int (Down Int) ([Int] -> [Int])
Modify Int (Down Int) ([Int] -> [Int]) :: *
= Modify
Int
(Down Int)
(->)
(Modify Int (Down Int) [] (Down Int))
(Modify Int (Down Int) [] (Down Int))
Vladislav
Я ожидал [Down Int] -> [Down Int] получить
Vladislav
Всё, разгадал
Vladislav
Третий кейс забыл
Vladislav
type family Modify (a :: k) (b :: k) (f :: kf) :: kf where
Modify a b a = b
Modify a b (f x) = (Modify a b f) (Modify a b x)
Modify a b c = c
Vladislav
В общем оборачивает оно нормально
Vladislav
*Main Data.List Data.Ord> :kind! Modify Int (Down Int) ([Int] -> [Int])
Modify Int (Down Int) ([Int] -> [Int]) :: *
= [Down Int] -> [Down Int]
Vladislav
но как этим дальше пользоваться у меня быстро разобраться не получилось
A64m
жаль что вот такие вот штуки
forall a. Modify a (Down a) (a -> a -> a)
не редьюсятся, конечно
Vladislav
да, печально
A64m
может на плагинах можно накостылить что-то более приближенное к цели
Vladislav
Это потому что там на бесконечные типы поправка. Например, в
*Main Data.List Data.Ord> :kind! forall a. Modify a (Down a) (Maybe a)
forall a. Modify a (Down a) (Maybe a) :: *
= Modify a (Down a) (Maybe a)
оно фейлится, потому что предполагает, что a ~ Maybe a возможно
Vladislav
У Эйзенберга это упомянуто в его пейпере про constrained type families
Vladislav
Для того чтобы продвинуться, нам нужно взять вот эту ветку:
Modify a b (f x) = (Modify a b f) (Modify a b x)
Чтобы ее взять, надо исключить вероятность всех предыдущих, в нашем случае:
Modify a b a = b
А чтобы это исключить, надо знать, что a /~ f, и GHC a /~ Maybe a не предполагает.
Vladislav
Хотя мог бы в теории, если бы все семьи типов были тотальными
Vladislav
type family Loop :: *
type instance Loop = Maybe Loop
Vladislav
а пока возможно такое, то мы имеем Loop ~ Maybe Loop, а значит потенциально a ~ Maybe a
A64m
а, т.е. даже могут пофиксить в некоем неопределенном будущем. хорошо
Vladislav
Ну да, там весь пейпер про то, как это фиксить
Vladislav
А потом он еще с докладом про это выступал
Vladislav
И сказал, типа, в Scala молодцы, что у них все семьи типов ассоциированы с классом, у них поэтому такой проблемы нет. Но сами скалисты не понимают, какой участи избежали, потому что даже не задумывались над этой проблемой (опять же по словам Эйзенберга)
A64m
я теперь даже вспомнил, что смотрел этот доклад
Anonymous
Известная картиночка https://i.redditmedia.com/FlXKab4jiLW1X5lBWAE8YzwOGb-ALF0reRqW3BULpYs.png?s=926985cc55c2e143b334c7537b438e4d точно так же применима к спорам об ООП/ФП
Anonymous
упс, должна была быть кортиночка про сторонников статической/динамической типизации и людей знакомых с теорией типов, но идея та же 😀
Dmitry
Пересечение социалисты+экономисты не пересекается с капиталистами? ;)
Евгений
Странно сравнивать теорию типов с economics
Евгений
Хотя бы потому, что теория типов основана на вере в познание, а economics на вере в невозможность познания
A64m
марксисты теперь в экономике разочаровались?
Dmitry
Почему это прям в economics вера в невозможность познания?
A64m
б-же упаси, на положениях хайека набор практикуемых в реальном имре практик не основан
A64m
в худшем случае на положениях фридмана
A64m
тем не менее он левее хайека
Евгений
Ты под левее понимаешь прогосударственнее? Или речь про отношение к знанию?
A64m
первое, конечно, про то где правее а где левее в отношении к знанию я не ориентируюсь
Евгений
A64m
в экономике нормально коррелирует обычно