【问题标题】:scalaz validation and list monadscalaz 验证和列表单子
【发布时间】:2011-08-10 12:06:57
【问题描述】:

我正在尝试提出类似于以下内容的内容:

val s: Validation[String, Int] = 1.success
def s2(i: Int): Validation[String, Int] = i.success

val result = for {
  i <- s
  j <- List(1, 2)
  k <- s2(j)
} yield "fine";

上面的代码无法编译,我理解,语法上没有意义。

我正在尝试以单子方式执行验证列表。我该如何实现?

【问题讨论】:

标签: validation scala scalaz


【解决方案1】:

如果您有A 的验证列表,您可以使用sequence 将其转换为A 列表的验证:

List(1, 2).map(s2).sequence[({type l[a]=Validation[String, a]})#l, Int] 

(如果我正确理解了这个问题)。所以你得到

val result = for {
  i <- s
  k <- List(1, 2).map(s2).sequence[({type l[a]=Validation[String, a]})#l, Int] 
} yield "fine"

【讨论】:

  • 优秀。这正是我想要的。谢谢。
  • 抱歉,回复得太早了。这几乎就是我想要的。这里计算列表中的所有验证。一旦我收到失败,我希望停止计算。我该怎么做?
  • 暂时无法测试,但尝试使用Stream(即惰性列表)代替List,或List(1, 2).view.map(s2)...
  • .view 只是无法编译。使用 Stream.from(-100) 显式创建的流(我使用了不同的 s 函数,以确保 i 大于 0)导致堆栈溢出。另请注意,如果您想要序列的“失败优先”语义,则需要导入 Validation.Monad._。
【解决方案2】:

您似乎正在使用验证来解决副作用。这不是它的目的。您在函数式编程中使用返回值。

for comprehension 中的验证在成功时继续进行,但在失败时中断并返回失败。

scala> def g(i: Int): Validation[String, Int] = { 
          println(i); if(i % 2 == 0) i.success else "odd".fail 
       }
g: (i: Int)scalaz.Validation[String,Int]

scala> val result = for {
     |   i <- g(1)
     |   j <- g(2)
     | } yield (i,j)
1
result: scalaz.Validation[String,(Int, Int)] = Failure(odd)

scala> val result = for {
     |   i <- g(2)
     |   j <- g(1)
     | } yield (i,j)
2
1
result: scalaz.Validation[String,(Int, Int)] = Failure(odd)


scala> val result = for {
     |   i <- g(2)
     |   j <- g(2)
     | } yield (i,j)
2
2
result: scalaz.Validation[String,(Int, Int)] = Success((2,2))


scala> val result = for {
     |   i <- g(1)
     |   j <- g(1)
     | } yield (i,j)
1
result: scalaz.Validation[String,(Int, Int)] = Failure(odd)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多