假设我们有两个值包含在不同的monad中(例如Try和Option):
val x: Option[Int] = Some(10)
val y: Try[Int] = Success(4)
我们希望得到值的总和。一个人会写
val z = for {
xval <- x
yval <- y
} yield xval + yval
但由于类型错误,它不会被编译。有没有惯用的Scala方法来解决这个问题?
答案 0 :(得分:3)
Scala标准库缺少一些有用的函数/抽象,但幸运的是有一个名为Scalaz的补充库,它提供了你需要的大部分内容。
特别是,正如所建议的那样,您正在寻找Monad变压器。请参阅以下这两篇文章:
http://eed3si9n.com/learning-scalaz/Monad+transformers.html
http://underscoreconsulting.com/blog/posts/2013/12/20/scalaz-monad-transformers.html
答案 1 :(得分:1)
使用Cats monad转换器OptionT:
import { Component } from '@angular/core';
import { of, from } from 'rxjs';
import { map, catchError, tap, retry} from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular 6';
constructor() {
of('a', 'b', 'c', 'd')
.pipe(
map(x => {
if (x === 'c') {
throw 'An error has occurred';
}
return x;
}),
tap(x => console.log('In tap: ', x)),
retry(3),
catchError(() => of('caught error!'))
)
.subscribe(x => console.log(x));
}
}
但是,返回类型为val z = (for {
xval <- OptionT.fromOption(x): OptionT[Try, Int]
yval <- OptionT.liftF(y)
} yield xval + yval).value
答案 2 :(得分:0)
Daniel Spiewak的Emm库能够合并多个monad,但由于它不遵守所有monadic法律,因此该库仅用于教学目的。
Emm Github:https://github.com/djspiewak/emm
Daniel在Emm上做了一个演讲:https://www.youtube.com/watch?v=E5Tri3Yow0U
我还遇到了FreeK,这是一个用于编写多个Free monad的库:https://github.com/ProjectSeptemberInc/freek