Size: a a a

2021 October 16

JS

Jerzy Syrowiecki in Haskell Start
интересно, что можно ещё и для саморазвития использовать hacktoberfest, не только для вклада в опенсорс
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Энергию новичков лучше направлять на что-то такое, чем оставлять без внимания и рисковать получить только очередные реквесты в репозитории вида "напиши hello world на своём языке"
источник

AP

Aleksei (astynax) Pi... in Haskell Start
Хотя духу мероприятия такое обучение с призами за счёт организаторов не соответствует, конечно
источник

SG

Serge S. Gulin in Haskell Start
В общем, с помощью чата и ссылок, кажется, моя задача решилась вот таким минимумом, в котором я разобрался, и который вроде бы даёт мне то, что хочется:
```
data UserRole = A | B | C deriving (Eq, Show)

class UserRoleValue (a :: UserRole) where
 _userRoleValue :: Proxy a -> UserRole

instance UserRoleValue ‘
A where
 _userRoleValue _
= A

… тут далее остальные инстансы
```
источник

SG

Serge S. Gulin in Haskell Start
Чего-то бОльшего мне пока и не надо, и это хорошо. 😄
источник

SG

Serge S. Gulin in Haskell Start
> Из значений в типы - сложнее всего.

Хотел избежать этого у себя, и, кажется, я понял, почему избежать этого может и не получится в конкретном случае.

Возьмем тот самый пример с ролями пользователя. Как мы можем представить роль пользователя без преобразования значение в тип? Как мне кажется, достаточно завернуть тип-свидетель в Maybe. Нечто вроде Maybe (Proxy ‘A). Далее при необходимости отобразить пользователю список ролей достаточно написать тайп-класс который будет осуществлять конверсию Proxy (a :: UserRole) в конкретное значение из UserRole. Это сделать довольно просто, вы уже показывали как.

Но зачем мне роли? Хотелось бы по этим ролям понимать какие операции пользователь может совершать над сущностями. Чтобы из системы типов было сразу видно: может пользователь что-то сделать или не может.

Достаточно просто написать таблицу-сопоставление между типам каинда UserRole и типами каинда UserOperation. Однако возвращаясь в реальность, у нас там Maybe (Proxy (a :: UserRole)) (здесь и выше это не синтаксис хаскеля, я просто пытаюсь отразить взаимосвязь).

Кажется вот тут я вступаю в потребность «из значений в типы», поскольку без этой возможность единственное, что я могу утверждать в системе типов, так это только то пользователь может иметь какие-то роли. Без работы со значениями уже не получится выкрутиться. Все так?
источник

JS

Jerzy Syrowiecki in Haskell Start
> Как мы можем представить роль пользователя без преобразования значение в тип?

как в динамике делают — передавать значение и проверять/ветвиться по нему на каждом шаге. да, менее безопасно, но работающее, проверенное десятилетиями решение.
источник

SG

Serge S. Gulin in Haskell Start
Хочется выйти на то, чтобы можно было писать следующее:

doSomeOperation :: (App m, UserContext u m, Has ‘SomeUserRole u) => …
источник

SG

Serge S. Gulin in Haskell Start
В моей голове как: есть монада приложения, запрос влетая в сервант обволакивается этой монадой. Если в запросе присутствует кука, то по ней вытаскивается пользователь, анализируется, далее всё обволакивается в монаду контекста пользователя с обнаруженными ролями. А дальше мы уже можем писать бизнес-логику, кодируя требования присутствия ролей прям в контексте.
источник

YS

Yan Shkurinskiy in Haskell Start
У меня бекенд с ролями, я когда его начинал писать, сделал просто матчинг поля и ветвление
источник

YS

Yan Shkurinskiy in Haskell Start
Ну это было два года назад правда
источник

YS

Yan Shkurinskiy in Haskell Start
Не хотел тогда морочиться
источник

SG

Serge S. Gulin in Haskell Start
Т.е. сигнатура функций допустимых операций для той или иной роли не отражает наличие конкретной роли?
источник

YS

Yan Shkurinskiy in Haskell Start
У меня для каждой роли просто отдельные функции
источник

YS

Yan Shkurinskiy in Haskell Start
И у них да, в сигнатуре роли нет
источник

[

[BRM]White Rabbit in Haskell Start
Звучит как "очень плохо, что в хаскеле объединили рекорды и адт, иначе мы были бы вынуждены прописывать каждую ветвь отдельным рекордом"
источник

[

[BRM]White Rabbit in Haskell Start
(хотя, конечно, никто не мешает так писать)
источник

SG

Serge S. Gulin in Haskell Start
Можете раскрыть подробнее? Мне пока не очевидно почему это одно и то же
источник

[

[BRM]White Rabbit in Haskell Start
data Person = Person { name :: Text, age :: Int}

data Cat = Cat { weight :: Int }

data CatOrPerson = C Cat | P Person


show :: CatOrPerson -> String
show (C cat) = foo cat
show (P person) = bar person

foo :: Cat -> String
bar :: Person -> String

Вынес ветви конструктора на уровень типа
источник

[

[BRM]White Rabbit in Haskell Start
Более полно:
Мысль в том, что хаскель позволяет совмещать суммы и рекорды, чего нет в некоторых других языках. Из-за этого момент "блин, я хочу работать с каждой веткой как с отдельным типом" наступает позже, когда уже написано много кода.

Хотя, конечно, это спорный момент и всегда можно просто сразу делать хорошо, чтобы не было плохо. У фичи(совмещение рекордов и адт) есть свои плюсы.
источник