Monad 变换用于理解

发布于 2024-12-12 08:46:55 字数 875 浏览 0 评论 0原文

考虑一下:

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)
}

我可以在 for 中添加 a 作为: a <- Some(A(c )) 但是隐式的呢?这是否意味着我的代码的设计发生了变化?

Consider:

def xs(c: String): Option[List[Long]] = ...

val ys: Stream[Long] = ...

Now I'd write a method something like:

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

but of course this doesn't compile, since the inferred type is Option[Option[Long]].

Is there a way in terms of scala syntax and standard library to get an Option[Long]? I know I can pattern match, but the question if it can be done using for comprehensions only just arised.


Thanks to tenshi for the answer, that does the job, however I just encountered another example of my problem:

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)
}

I can add a in the for as: a <- Some(A(c)) but what about the implicit? Should that imply a design change in my code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜巴黎 2024-12-19 08:46:57

为什么要使用 2 个嵌套的 for 理解?难道不应该有人做这项工作吗?

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

更新

关于您的第二个示例。您可以在其他地方定义隐式并导入它或在方法的开头定义它,但我想您希望使其范围尽可能窄。在这种情况下,您可以直接在 for 理解中使用 block:

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 

Why are you using 2 nested for comprehensions? Shouldn't one do the job?

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

Update

About your second example. You can define implicit elsewhere and import it or define it in the beginning of the method, but I guess you want to make it's scope as narrow as possible. In this case you can use block directly in the for comprehension:

def getU_2(oc: Option[String]): Option[U] = for {
   c <- oc
   a <- {
       implicit val someImplicit: T = new T
       getU(new A(c))
   }
} yield a

or (probably the simplest) provide implicit parameter explicitly:

def getU_2(oc: Option[String]): Option[U] = for {
   c <- oc
   a <- getU(new A(c)(new T))
} yield a 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文