#scala #monad-transformers #for-comprehension
#scala #монадные трансформаторы #для понимания
Вопрос:
Рассмотрим:
def xs(c: String): Option[List[Long]] = ...
val ys: Stream[Long] = ...
Теперь я бы написал метод что-то вроде:
def method(oc: Option[String]): Option[Long] = for {
c <- oc
list <- xs(c)
} yield{
for {
first <- ys.find(list contains _)
} yield first
}
но, конечно, это не компилируется, поскольку предполагаемый тип — Option[Option[Long]] .
Есть ли способ с точки зрения синтаксиса scala и стандартной библиотеки получить опцию [Long]? Я знаю, что могу сопоставить шаблон, но вопрос, можно ли это сделать, используя для понимания, только что возник.
Спасибо tenshi за ответ, который выполняет свою работу, однако я только что столкнулся с другим примером моей проблемы:
class T
class U
class A(t: String)(implicit x: T)
def getU(a: A): Option[U] = ...
def getU_2(oc: Option[String]): Option[U] = for{
c <- oc
} yield{
implicit val someImplicit: T = new T
val a = A(c)
getU(a)
}
Я могу добавить a
в for as: a <- Some(A(c))
но как насчет неявного? Должно ли это означать изменение дизайна в моем коде?
Комментарии:
1. Не уверен в ваших намерениях, но у вас есть синтаксическая ошибка 2. Вы забыли
for
ключевое слово в начале тела метода, и вам следует использовать<-
infirst = ys.find(list contains _)
.2. Спасибо за ответ и комментарий, я обновил вопрос.
3. Ну, я думаю, мне уже слишком поздно кодировать или просто слишком взволнован написанием в функциональном стиле :), это исправило это:
def getU_2(oc: Option[String]): Option[U] = { implicit .. for { c <- oc a <- Some(A(c)) u <- getU(a) } yield u }
Ответ №1:
Почему вы используете 2 вложенных for
понимания? Разве не следует выполнять эту работу?
def method(oc: Option[String]): Option[Long] =
for {
c <- oc
list <- xs(c)
first <- ys.find(list contains _)
} yield first
Обновить
О вашем втором примере. Вы можете определить implicit в другом месте и импортировать его или определить его в начале метода, но я предполагаю, что вы хотите сделать его область действия как можно более узкой. В этом случае вы можете использовать block непосредственно в for
понимании:
def getU_2(oc: Option[String]): Option[U] = for {
c <- oc
a <- {
implicit val someImplicit: T = new T
getU(new A(c))
}
} yield a
или (вероятно, самый простой) явно укажите неявный параметр:
def getU_2(oc: Option[String]): Option[U] = for {
c <- oc
a <- getU(new A(c)(new T))
} yield a