Почему валидация нарушает законы монады?
На SO дано объяснение, почему валидация, например, в scalaz, cats (Scala) или Arrow (Kotlin) не может быть монадой.
Насколько я понимаю, это потому, что они смоделировали монады с точки зрения аппликативных функторов, а желаемое поведение Валидации как аппликативного (сбор всех инвалидов) отличается от желаемого поведения Валидации как монады (проверки последовательности и быстрое сбой на первый недействительный). В результате вам нужно преобразовать валидацию в любую (которая является монадой), если вы хотите быстро потерпеть неудачу.
На https://groups.google.com/forum/ они упоминают, что проверка не является монадой, потому что следующее свойство не будет выполняться:
x <|*|> y === x >>= (a => y map ((a, _)))
Но, глядя на определение монады, собственность выше не является частью законов монады. Итак, является ли это результатом того факта, что монады реализованы в терминах аппликативов, или это свойство является предпосылкой для того, чтобы стать монадой?
Все эти рассуждения более высокого рода совершенно новы для меня, но в моем ограниченном понимании FP у меня может быть тип данных проверки, который имеет один тип поведения, когда используется как аппликативное (накапливаются инвалиды), и другое поведение, когда используется как монада (быстро проваливается).
1 ответ
Вы все правильно поняли. Да, законный монадный инстанс для Validation
возможно. Проблема в том, что это даст два разных Applicative
случаи для Validation
: один накапливает ошибки, другой происходит от экземпляра монады и быстро терпит неудачу. Это может привести к несогласованности классов типов: поведение программы в зависимости от того, как был получен экземпляр класса типов.
Собственность, которую вы упоминаете,
x <|*|> y === x >>= (a => y map ((a, _)))
может служить определением <|*|>
с точки зрения >>=
а также map
и, следовательно, автоматически выполняется для Аппликатива, полученного из Монады. Проблема в том, что уже есть другой Аппликатив с другим поведением <|*|>
,