Scala是意外的类型行为

jed*_*sah 1 types scala

为什么这个代码段没有打印出来:"你成功实现了这个功能"

细节:

为什么val实际上看起来类型为List [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

// Flatten a nested list structure

def flatten[T](list: List[Either[List[T], T]]): List[T] = list flatMap {
    // TODO: Implement
    case list: List[T]  => list
    case element: T     => List(element)
}

implicit def ElementToEitherLeft[T](obj: T) = Left(obj)
implicit def ElementToEitherRight[T](obj: T) = Right(obj)

val list: List[Either[List[Int], Int]] = List(List(1, 1), 2, List(3, 5))
val actual: List[Int] = flatten[Int](list)
val expected = List(1, 1, 2, 3, 5)
if (actual == expected)     print("You successfully implemented the function")
else                        print("Unfortunatly, that's not quite rigth yet")
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 7

当你编译你的时候flatten你应该看到这样的警告:

warning: there were 2 unchecked warnings; re-run with -unchecked for details
Run Code Online (Sandbox Code Playgroud)

如果你用with编译-unchecked,你会看到这个:

<console>:9: warning: non variable type-argument T in type pattern List[T] is unchecked since it is eliminated by erasure
           case list: List[T]  => list
                      ^
<console>:10: warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure
           case element: T     => List(element)
Run Code Online (Sandbox Code Playgroud)

简而言之,flatMap不打算Either为你打开你的物品,你写的东西只是因为关于类型擦除和模式匹配的一些不愉快的事实而编译.

幸运的是,这是一个简单的解决方案:

 def flatten[T](list: List[Either[List[T], T]]): List[T] = list flatMap {
   case Left(list)  => list
   case Right(item) => item :: Nil
 }
Run Code Online (Sandbox Code Playgroud)

或者,甚至更好:

def flatten[T](list: List[Either[List[T], T]]): List[T] =
  list.flatMap(_.fold(identity, List(_)))
Run Code Online (Sandbox Code Playgroud)

要么按预期工作要么.