在Scala中将列表用作monad
我想知道在在Scala中将列表用作monad,scala,Scala,我想知道在列表上应用一些操作(如果它不是空的)的惯用方法是什么,如果列表是空的,则返回空的列表(Nil) val result= myList match { case Nil => Nil // this one looks bad for me case nonEmpty => myService.getByFilters(nonEmpty) } 只需在列表上使用map操作将触发循环,但我希望在选项类型上实现与map相同的结果-即,如果list为
列表
上应用一些操作(如果它不是空的)的惯用方法是什么,如果列表是空的,则返回空的列表
(Nil
)
val result= myList match {
case Nil => Nil // this one looks bad for me
case nonEmpty => myService.getByFilters(nonEmpty)
}
只需在列表上使用
map
操作将触发循环,但我希望在选项
类型上实现与map
相同的结果-即,如果list
为非空,则只执行一次,如果list
为空,则不执行任何操作我认为您的设计可能不太正确。您应该能够将任何列表传递到getByFilters
函数中,并且它应该只处理任何长度的列表。因此,应该没有必要进行此类检查
如果不可能进行设计更改,则没有问题,如果:
val result = if(myList.isEmpty) Nil else myService.getByFilters(myList)
它的惯用用法是因为if
返回值。也许还有其他干净的方法,我不知道
如果只需要非空列表参数,可以使用HList
或者使用以下技巧:
def takesNonEmptyList[T](head: T, tail: T *): List[T] = head :: tail.toList
你可以做一些假造的事情让它看起来像是惯用的,但我不推荐。不清楚也不必要的复杂:
def getByFilters(xs: List[Int]) = xs.filter(_ % 2 == 0)
val res = l.headOption.map(_ :: l.tail).map(getByFilters).getOrElse(Nil)
println(res)
打印列表(2,4)
如果您确实需要,您可以实现自己的语义:
implicit class MySpecialList[T](xs: List[T]) {
def mapIfNotEmpty[R](f: List[T] ⇒ List[R]): List[R] =
if (xs.isEmpty) Nil else f(xs)
}
def getStuff(xs: List[Int]) = xs.map(_ + " OK")
val x: List[Int] = List(1,2,3)
val y: List[Int] = List()
def main(args: Array[String]): Unit = {
val xx = x.mapIfNotEmpty(getStuff) // List("1 OK", "2 OK", "3 OK")
val yy = y.mapIfNotEmpty(getStuff) // List()
}
List
中有方法headOption
,因此可以使用选项语义将List
提升到option[List]
:
import scala.collection.TraversableLike
implicit class TraversableOption[T <: TraversableLike[_, T]](traversable: T) {
def opt: Option[T] = traversable.headOption.map(_ => traversable)
}
通过分别调用每个筛选器服务
myList.flatMap(filter => myService.getByFilters(List(filter)))
如果myList
为空,则它将获取一个空列表。如果性能可能是一个问题,也要考虑一个具有的并行版本。
myList.par
是的,我想在myService#getByFilters
中移动此逻辑,但后来决定从该方法返回空列表是不正确的,因为在空列表参数列表(过滤器列表)的情况下,它将返回所有值而不应用过滤器。所以我决定,如果列表为空,则在myService#getByFilters
中抛出异常更为正确。关心空的参数列表是客户机代码的责任。注意,在这种上下文中说“将列表用作monad”是不正确的。List monad有一个特定的定义,它的fmap
函数是map
。别的东西既不是单子也不是函子。
myList.par