Pull to refresh

Comments 7

Интересная статья! Спасибо за перевод.


После прочтения остался вопрос: тут вся валидация — это проверка того, что Maybe-поля обязательно присутствуют. Интересно было бы взглянуть на примеры, когда:


  1. Нужно проверить, что возраст не меньше 18, а имя написано латиницей
  2. Имя должно начинаться на "Ы", если возраст между 34 и 42 годами, и на "Ъ", если возраст между 101 и 111 годами
  3. Получить не Maybe Person, а Either WhyInvalid Person с описанием того, почему проверка не понравилась.

Примерно так обычно выглядит продуктовая валидация исходя из моего опыта — поэтому и интересно взглянуть на то, как Higher-Kinded Data помогает в этих случаях.

На третий вопрос — проще, чем кажется. Вместо типа Person' Maybe надо использовать тип Person' (Either WhyInvalid). И дописать обобщёную функции валидации для типа Either (отличатья будет не телом функции, лишь типом).
Что касается первого и второго вопроса — валидировать поля можно при заполнении типа Person' Maybe.
mPerson :: Perosn' Maybe
mPerson = Peson {
  ...
  pAge = readMaybe ioAge >= (\age -> if age< 18 then Nothing else Just age),
 ...
}

Более подробно — можете глянуть мою статью Зачем нужны все эти функторы и монады?
Что касается более вычурной валидации — просто вынести валидацию из тела записи в дополнительную функцию
mPerson :: Perosn' Maybe
mPerson = 
  let pAge = readMaybe ioAge >= (\age -> if age < 18 then Nothing else Just age) in
  let pName = pAge >= (\age -> 
      if age > 34 && age < 42 then ... 
      else if age > 101 && age < 11 then ...
      else ... ) in
  Peson {
...
pName = pName,
pAge = pAge,
...
}
UFO just landed and posted this here
Я прочитал статью несколько раз и все равно ничего не понял. Какую задачу тут помогли решить поднятые до «родов» (впервые слышу такой перевод, я привык к «видам») параметризованные типы данных?

И мы будем валидировать данные лишь в том случае, когда валидны все поля записи.

-- Этот код будет работать и для Identity, так как Identity так же имеет экземпляр класса Applicative:
Person <$> name <*> age


В коде реального приложения подобные заигрывания с семействами типов лишь для того, чтобы из Identity a вытащить a очень больно ударят по его читаемости. Когда вы читаете сигнатуру какой-нибудь функции, будет лучше, если вы сразу понимаете, Identity там или что-то другое.
Хороший вопрос.
1) Род или вид — ещё нет устойчивых наименований, я всё же склоняюсь к наименованиям русскоязычной теории категорий
2) Мы всё же поднимаем параметры не до родов, поскольку любой тип итак имеет род (как правило звёздочку), а до более высоких родов (чем звёздочка)
3) Ответ на основной ваш вопрос — для того, чтоб совместить 2 типа данных(или более) в один.
4) Да, существует функтор для Identity, но функцию validate мы применяем к Person' Maybe, а не Person' Identity
1) Я сомневаюсь, что kind как-то вообще связан с теорией категорий (может вы спутали с теорией типов?), скиньте мне пожалуйста ссылку, если я не прав.
2) Параметризованные типы — это типы, имеющие параметры, а не сами параметры.
3) Какие 2 типа данных имеются ввиду? И зачем иметь два разных типа?
4) Я не имел ввиду функцию `validate`. Не думаю, что это выглядит как ответ на вопрос.

На мой взгляд, это ужасная статья для перевода. Мало того, что она использует мощную систему типов для решения несуществующих проблем, так еще и отпугивает людей, которым действительно интересен Haskell.
1) упс, сори, да, теория типов
2) это не противоречит тому, что сказал я
3) Зачем 2 разных типа — это отдельный вопрос. Person' Maybe и Person' Identity
4) функторы/мондаы/… спокойно проникают сквозь обёртку Identity. При этом нет необходимости разворачивать Identity а в а, это делает за нас семейство типов.
Об этом была моя предыдущая статья Великая сила newtypes про coerce

Как на меня — это прекрасная статья для ознакомления с семьями/семействами типов, высокими родами и генериками. Пример мышления далеко ЗА императивным мышлением
Sign up to leave a comment.

Articles