猫的NonEmptyList与Scala stdlib ::

yhm*_*yhm 4 scala scala-cats

我最近正在学习猫库,并且遇到过名为NonEmptyList的此类。

阅读了api之后,我不禁想知道是什么使猫的作者创建了一个新类,而不是利用内置的(::)并使用类型类对其进行扩展。它甚至没有在cats github页面上列出,所以我来这里问这个问题。也许是因为cons是List的子类型?(尽管我不知道它的含义)

::和NEL有什么区别?为什么猫的作者不得不写NEL而不是使用::?

Mic*_*hta 5

NonEmptyList不进行扩展的主要原因List开发人员在API中包含假设的经验

首先,请注意,::所有方法List都有可能会引起误解,这使得更难以根据更强大的假设来设计更好的API。此外,List没有任何直接返回的方法::,这意味着开发人员需要手动维护非空抽象。

让我给你看一个例子,说明我在实践中的意思:

// NonEmptyList usage is intuitive and types fit together nicely
val nonEmpty: NonEmptyList[Int] = NonEmptyList.of(1, 2, 3)
val biggerNonEmpty: NonEmptyList[Int] = 0 :: nonEmpty
val nonEmptyMapped: NonEmptyList[Int] = nonEmpty.map(_ * 2)

// :: has lots of problems
// PROBLEM: we can't easily instantiate ::
val cons: ::[Int] = 1 :: 2 :: 3 :: Nil // type mismatch; found: List[Int]; required: ::[Int]
val cons: ::[Int] = new ::[Int](1, ::(2, ::(3, Nil)))

// PROBLEM: adding new element to Cons returns List
val biggerCons: ::[Int] = 0 :: cons // type mismatch; found: List[Int]; required: ::[Int]

// PROBLEM: ::.map returns List
val consMapped : ::[Int] = cons.map(_ * 2) // type mismatch; found: List[Int]; required: ::[Int] 
Run Code Online (Sandbox Code Playgroud)

需要注意的是NonEmptyList有方法,返回List,即filterfilterNotcollect。为什么?因为筛选NonEmptyList可能意味着您筛选出了所有元素,所以列表可以成为空元素。

这就是使整个非空抽象如此强大的原因。通过正确使用函数的输入和输出类型,可以对有关API的假设进行编码。::没有提供这种抽象。