Почему валидация не является монадой?

пример использования:

def div2(i: Int): Validation[String, Int] = 
    if (i%2 == 0) Validation.success(i/2)
    else Validation.failure("odd")

def div4(i: Int) = for {
    a <- div2(i)
    b <- div2(a)
} yield b

ошибка: невозможно отменить применение типа scalaz.Validation[String,Int] в конструкторе типа типа M[_], который классифицируется классом типов scalaz.Bind.

Я предполагаю, что ошибка вызвана тем, что компилятор не может найти экземпляр Monad для Validation[String, Int]

Я могу сделать один для себя, например:

object Instances {
implicit def validationMonad[E] = new Monad[({type L[A] = Validation[E, A]})#L] {
    override def point[A](a: => A) =
        Validation.success(a)
    override def bind[A, B](fa: Validation[E, A])(f: A => Validation[E, B]) =
        fa bind f
}
}

но почему его еще нет у Validation? в конце концов, для Validation уже определен метод bind.

кроме того, я больше не могу совмещать import Validation._ и import Instances._ (мне потребовалось много времени, чтобы понять...), из-за другой сложной ошибки...
неоднозначные неявные значения: что-то вроде validationMonad (мой экземпляр) и метода ValidationInstances1 в трейте ValidationInstances2... оба соответствуют некоторым Functor of Validation...

я должен изменить источник scalaz? или я что-то упускаю~?
помогите пожалуйста~

Я использую scalaz 7.0.0-M2


person Chris    schedule 31.08.2012    source источник


Ответы (2)


Как обсуждалось в группе Scalaz, проблема заключается в том, что ap накапливать ошибки, тогда как (псевдо-) монадическая композиция будет работать только со значением части Validation.

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

person Debilski    schedule 31.08.2012
comment
хм ... может быть, я не слишком хорошо разбираюсь в функциональном программировании, я все еще не мог понять, почему свойство (в обсуждении) должно сохраняться ... но я думаю, что это уже ответило на мой вопрос здесь, спасибо ~ - person Chris; 01.09.2012
comment
но как побочный вопрос, нет ли выхода для моего варианта использования? кроме определения экземпляра Monad самостоятельно~? есть ли плохая сторона моего подхода? - person Chris; 01.09.2012
comment
@chris Если вас не волнует автоматическое добавление ошибки, очевидным выбором будет полный переход на scalaz.\/ (правосторонняя замена Scalaz для Either), которая имеет нужную вам семантику и, следовательно, может быть менее запутанной для других людей. (Реализация правила, которое в основном нарушает монадные и аппликативные законы, может работать совершенно хорошо и предсказуемо, но, тем не менее, может оказаться немного запутанным.) - person Debilski; 19.09.2012
comment
@chris Я бы сказал, что в вашем подходе есть только одна маленькая проблема: некоторые люди сочтут удивительным, что законы монад нарушаются. Но интуитивно, на мой взгляд, в данном случае имеет смысл нарушать законы монад. - person Owen; 13.07.2013

Проблема в том, что аппликативный функтор, как подразумевается монадой, не равен действительному аппликативному функтору.

person oxbow_lakes    schedule 31.08.2012
comment
Не могли бы вы объяснить, что подразумевается, а что на самом деле? Я мало что знаю об этих типах классов... - person Chris; 01.09.2012
comment
почтительный удар @oxbow_lakes - person Kevin Meredith; 18.01.2014
comment
Вы можете на законных основаниях вывести аппликативный интерфейс из монадического связывания/цепочки (это просто цепная операция для получения внутреннего значения (функции), а затем сопоставление со вторым аппликативом с использованием этой функции). Но если вы на самом деле реализуете это, вы получите аппликативное поведение, которое вы ожидаете от любого типа, а не то, которое вы ожидаете от проверки. - person Dtipson; 26.08.2016