Scala中的类序函数

时间:2015-03-31 04:01:23

标签: scala haskell

鉴于List[Either[A,B]],我可以在Haskell中使用sequence来提取整个List Right[B]Left[A]

Prelude> sequence [Left "bad", Right 555]
Left "bad"
Prelude> sequence [Right 4534, Right 555]
Right [4534,555]

我不确定此方法是否符合sequence的定义,但它是处理List[Either[A,B]] => Either[A, List[B]]的一个很小的功能。

scala> def f[A, B](es: List[Either[A, B]]): Either[A, List[B]] = es match {
     |   case Right(x) :: xs      => f(xs).right.map(y => x :: y)
     |   case Nil                 => Right(Nil)
     |   case left @ Left(_) :: _ => left
     | }

但是我收到了这个我不理解的错误。

<console>:10: error: type mismatch;
 found   : scala.collection.immutable.::[Either[?A3,?B3]] where type ?B3 <: B (this is a GADT skolem), type ?A3 <: A (this is a GADT skolem)
 required: Either[A,List[B]]
         case left @ Left(_) :: _ => left
                                     ^

我在这里做错了什么?

1 个答案:

答案 0 :(得分:6)

错误消息显示left的类型为Either[A, B],但f的预期类型为Either[A, List[B]]

你需要在案例中解构Left,然后在表达式中重构它。这看起来很愚蠢,但你要记住,分支中的Left(x)被标记为与你想要的类型不同。

| case Left(x) :: _ => Left(x)

Haskell会给你一个类似的错误:

f :: Either a b -> Either a [b]
f l@(Left x) = l

Couldn't match type ‘b’ with ‘[b]’
  ‘b’ is a rigid type variable bound by
      the type signature for f :: Either a b -> Either a [b]
      at /Users/Jake/Code/Haskell/L.hs:3:6
Expected type: Either a [b]
  Actual type: Either a b
Relevant bindings include
  l :: Either a b (bound at /Users/Jake/Code/Haskell/L.hs:4:3)
  f :: Either a b -> Either a [b]
    (bound at /Users/Jake/Code/Haskell/L.hs:4:1)
In the expression: l
In an equation for ‘f’: f l@(Left x) = l