在scala中,如何定义两个Option参数的加法?具体来说,让我们说它们是Int
类型的包装器(我实际上使用的是双打映射,但这个例子更简单).
我尝试了以下但它只是给了我一个错误:
def addOpt(a:Option[Int], b:Option[Int]) = {
a match {
case Some(x) => x.get
case None => 0
} + b match {
case Some(y) => y.get
case None => 0
}
}
Run Code Online (Sandbox Code Playgroud)
编辑添加:
在我的实际问题中,我添加了两个映射,这些映射是稀疏矢量的替换.因此,无案例返回Map [Int,Double],而+实际上是++(在stackoverflow.com/a/7080321/614684处调整)
oxb*_*kes 26
当你意识到你可以站在巨人的肩膀上并利用常见的抽象和为使用它们而构建的库时,你可能会发现生活变得容易多了.为此,这个问题基本上是关于处理 幺半群(请参阅下面的相关问题以获取更多相关信息),并且所讨论的库称为scalaz.
使用scalaz FP,这只是:
def add(a: Option[Int], b: Option[Int]) = ~(a |+| b)
Run Code Online (Sandbox Code Playgroud)
对于任何幺半群M来说,这更有用:
def add[M: Monoid](a: Option[M], b: Option[M]) = ~(a |+| b)
Run Code Online (Sandbox Code Playgroud)
更有用的是,它适用于放置在Foldable
容器内的任意数量:
def add[M: Monoid, F: Foldable](as: F[Option[M]]) = ~as.asMA.sum
Run Code Online (Sandbox Code Playgroud)
需要注意的是一些相当有用类群,除了明显的Int
,String
,Boolean
分别是:
Map[A, B: Monoid]
A => (B: Monoid)
Option[A: Monoid]
事实上,提取自己的方法几乎不值得花时间:
scala> some(some(some(1))) #:: some(some(some(2))) #:: Stream.empty
res0: scala.collection.immutable.Stream[Option[Option[Option[Int]]]] = Stream(Some(Some(Some(1))), ?)
scala> ~res0.asMA.sum
res1: Option[Option[Int]] = Some(Some(3))
Run Code Online (Sandbox Code Playgroud)
问:什么是幺半群?
monoid是在此操作下
M
存在关联二进制操作(M, M) => M
和标识的类型I
,mplus(m, I) == m == mplus(I, m)
以便对于所有m
类型M
问:什么是|+|
?
这只是
mplus
二进制操作的scalaz速记(或ASCII疯狂,ymmv)
问:什么是~
?
它是一个一元运算符,意思是"或身份",它被scalaz库改进(使用scala的隐式转换)
Option[M]
if ifM
是一个monoid.显然非空选项会返回其内容; 一个空选项被monoid的标识所取代.
问:什么是asMA.sum
?
A
Foldable
基本上是可以折叠的数据结构(例如foldLeft
,像).回想一下,foldLeft
取一个种子值和一个操作来组成连续的计算.在求和幺半群的情况下,种子值是身份I
,操作是mplus
.因此你可以打电话asMA.sum
给Foldable[M : Monoid]
.您可能需要使用,asMA
因为名称与标准库的sum
方法发生冲突.
Lui*_*hys 10
def addOpts(xs: Option[Int]*) = xs.flatten.sum
Run Code Online (Sandbox Code Playgroud)
这适用于任意数量的输入.
如果它们都默认为0,则不需要模式匹配:
def addOpt(a:Option[Int], b:Option[Int]) = {
a.getOrElse(0) + b.getOrElse(0)
}
Run Code Online (Sandbox Code Playgroud)
(根据要求在答案中重复上面的评论)
您没有以正确的方式提取选项的内容。当您与 匹配时case Some(x)
,x
是选项(type )内的值Int
,并且您不会调用get
它。做就是了
case Some(x) => x
Run Code Online (Sandbox Code Playgroud)
反正如果你想要内容还是默认的a.getOrElse(0)
比较方便
归档时间: |
|
查看次数: |
1414 次 |
最近记录: |