Трансформатор монад для понимания

Рассмотреть возможность:

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 и стандартной библиотеки получить Option [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)) но как насчет неявного? Должно ли это означать изменение дизайна моего кода?


person Carlos López-Camey    schedule 30.10.2011    source источник
comment
Не уверен в ваших намерениях, но у вас есть 2 синтаксических ошибки. Вы забыли ключевое слово for в начале тела метода и должны использовать <- в first = ys.find(list contains _).   -  person tenshi    schedule 30.10.2011
comment
Спасибо за ответ и комментарий, я обновил вопрос.   -  person Carlos López-Camey    schedule 30.10.2011
comment
Ну, я думаю, что мне просто слишком поздно кодить или я слишком взволнован написанием в функциональном стиле :), это исправило: def getU_2(oc: Option[String]): Option[U] = { implicit .. for { c <- oc a <- Some(A(c)) u <- getU(a) } yield u }   -  person Carlos López-Camey    schedule 30.10.2011


Ответы (1)


Почему вы используете 2 вложенных понимания for? Разве не следует выполнять работу?

def method(oc: Option[String]): Option[Long] = 
    for { 
        c <- oc
        list <- xs(c)
        first <- ys.find(list contains _)
    } yield first 

Обновлять

О вашем втором примере. Вы можете определить неявное в другом месте и импортировать его или определить в начале метода, но я думаю, вы хотите сделать его область действия как можно более узкой. В этом случае вы можете использовать блок непосредственно в понимании 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 
person tenshi    schedule 30.10.2011