Монадный трансформер для понимания - PullRequest
1 голос
/ 30 октября 2011

Рассмотрим:

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]? Я знаю, что могу сопоставить с шаблоном, но вопрос, можно ли это сделать, используя для понимания только что возникший вопрос.


Спасибо Тэнши за ответ, который выполняет свою работу, однако я только что столкнулся с другим примером моей проблемы:

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 в качестве: a <- Some(A(c)) а как насчет неявного? Должно ли это означать изменение дизайна в моем коде?

1 Ответ

7 голосов
/ 30 октября 2011

Почему вы используете 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 
...