标签: for-comprehension

对flatMap/Map转换的理解感到困惑

我似乎真的不了解Map和FlatMap.我无法理解的是for-comprehension是如何嵌套调用map和flatMap的.以下示例来自Scala中的Functional Programming

def bothMatch(pat:String,pat2:String,s:String):Option[Boolean] = for {
            f <- mkMatcher(pat)
            g <- mkMatcher(pat2)
 } yield f(s) && g(s)
Run Code Online (Sandbox Code Playgroud)

翻译成

def bothMatch(pat:String,pat2:String,s:String):Option[Boolean] = 
         mkMatcher(pat) flatMap (f => 
         mkMatcher(pat2) map (g => f(s) && g(s)))
Run Code Online (Sandbox Code Playgroud)

mkMatcher方法定义如下:

  def mkMatcher(pat:String):Option[String => Boolean] = 
             pattern(pat) map (p => (s:String) => p.matcher(s).matches)
Run Code Online (Sandbox Code Playgroud)

模式方法如下:

import java.util.regex._

def pattern(s:String):Option[Pattern] = 
  try {
        Some(Pattern.compile(s))
   }catch{
       case e: PatternSyntaxException => None
   }
Run Code Online (Sandbox Code Playgroud)

如果有人能够阐明在这里使用map和flatMap背后的理由,那将会很棒.

monads scala map for-comprehension

82
推荐指数
3
解决办法
3万
查看次数

withFilter而不是filter

在使用map,flatmap等函数后,使用withFilter而不是过滤器总是更高效吗?

为什么只支持map,flatmap和foreach?(预期的功能如forall/exists)

scala lazy-evaluation for-comprehension scala-collections

78
推荐指数
2
解决办法
2万
查看次数

在Scala上键入不匹配以便理解

为什么这种结构会导致Scala中出现类型不匹配错误?

for (first <- Some(1); second <- List(1,2,3)) yield (first,second)

<console>:6: error: type mismatch;
 found   : List[(Int, Int)]
 required: Option[?]
       for (first <- Some(1); second <- List(1,2,3)) yield (first,second)
Run Code Online (Sandbox Code Playgroud)

如果我用List切换Some,它编译得很好:

for (first <- List(1,2,3); second <- Some(1)) yield (first,second)
res41: List[(Int, Int)] = List((1,1), (2,1), (3,1))
Run Code Online (Sandbox Code Playgroud)

这也很好:

for (first <- Some(1); second <- Some(2)) yield (first,second)
Run Code Online (Sandbox Code Playgroud)

for-loop scala type-mismatch for-comprehension scala-option

77
推荐指数
3
解决办法
2万
查看次数

使用带有Scala的Eithers"for"语法

据我了解,Scala"for"语法与Haskell的monadic"do"语法非常相似.在Scala中,"for"语法通常用于Lists和Options.我想将它与Eithers 一起使用,但默认导入中不存在必要的方法.

for {
  foo <- Right(1)
  bar <- Left("nope")
} yield (foo + bar)

// expected result: Left("nope")
// instead I get "error: value flatMap is not a member..."
Run Code Online (Sandbox Code Playgroud)

这个功能是通过一些导入提供的吗?

有一个轻微的障碍:

for {
  foo <- Right(1)
  if foo > 3
} yield foo
// expected result: Left(???)
Run Code Online (Sandbox Code Playgroud)

对于列表,它将是List().因为Option,它会None.Scala标准库是否为此提供了解决方案?(或许scalaz?)怎么样?假设我想为Either提供我自己的"monad实例",我怎么能这样做?

monads scala typeclass either for-comprehension

40
推荐指数
3
解决办法
1万
查看次数

Scala for-comprehensions中的未来[选项]

我有两个返回期货的功能.我试图使用for-yield理解将第一个函数的修改结果输入到另一个函数中.

这种方法有效:

  val schoolFuture = for {
    ud <- userStore.getUserDetails(user.userId)
    sid = ud.right.toOption.flatMap(_.schoolId)
    s <- schoolStore.getSchool(sid.get) if sid.isDefined
  } yield s
Run Code Online (Sandbox Code Playgroud)

但是我对那里的"if"感到不满意,似乎我应该可以使用地图了.

但是当我尝试使用地图时:

  val schoolFuture: Future[Option[School]] = for {
    ud <- userStore.getUserDetails(user.userId)
    sid = ud.right.toOption.flatMap(_.schoolId)
    s <- sid.map(schoolStore.getSchool(_))
  } yield s
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

[error]  found   : Option[scala.concurrent.Future[Option[School]]]
[error]  required: scala.concurrent.Future[Option[School]]
[error]         s <- sid.map(schoolStore.getSchool(_))
Run Code Online (Sandbox Code Playgroud)

我玩了几个变种,但没有找到任何有吸引力的工作.任何人都可以提出更好的理解和/或解释我的第二个例子有什么问题吗?

这是Scala 2.10的一个最小但完整的可运行示例:

import concurrent.{Future, Promise}

case class User(userId: Int)
case class UserDetails(userId: Int, schoolId: Option[Int])
case class School(schoolId: Int, name: String)

trait Error

class UserStore { …
Run Code Online (Sandbox Code Playgroud)

scala future for-comprehension

34
推荐指数
3
解决办法
2万
查看次数

Scala中的方法参数验证,用于理解和monad

我正在尝试验证无效方法的参数,但我找不到解决方案......

谁能告诉我该怎么办?

我正在尝试这样的事情:

  def buildNormalCategory(user: User, parent: Category, name: String, description: String): Either[Error,Category] = {
    val errors: Option[String] = for {
      _ <- Option(user).toRight("User is mandatory for a normal category").right
      _ <- Option(parent).toRight("Parent category is mandatory for a normal category").right
      _ <- Option(name).toRight("Name is mandatory for a normal category").right
      errors : Option[String] <- Option(description).toRight("Description is mandatory for a normal category").left.toOption
    } yield errors
    errors match {
      case Some(errorString) => Left( Error(Error.FORBIDDEN,errorString) )
      case None =>  Right( buildTrashCategory(user) )
    }
  }
Run Code Online (Sandbox Code Playgroud)

monads scala either for-comprehension

33
推荐指数
3
解决办法
7950
查看次数

print中的scala for-comprehension

为了理解,我不能只是提出一个印刷声明:

def prod (m: Int) = {
  for (a <- 2 to m/(2*3);
    print (a + "  ");
    b <- (a+1) to m/a;
    c = (a*b) 
    if (c < m)) yield c
}
Run Code Online (Sandbox Code Playgroud)

但我可以通过虚拟任务轻松绕过它:

def prod (m: Int) = {
  for (a <- 2 to m/(2*3);
    dummy = print (a + "  ");
    b <- (a+1) to m/a;
    c = (a*b) 
    if (c < m)) yield c
}
Run Code Online (Sandbox Code Playgroud)

作为副作用,并且仅在开发中的代码中使用(到目前为止),是否有更好的临时解决方案?

是否有一个严重的问题为什么我不应该使用它,除了副作用?

更新显示真实代码,其中调整一个解决方案比预期更难:

从与Rex Kerr的讨论来看,必要性已经上升到显示原始代码,这有点复杂,但似乎与问题无关(2x .filter,最后调用方法),但是当我试图将Rex'模式应用到它我失败了,所以我在这里发布:

  def prod (p: Array[Boolean], max: Int) …
Run Code Online (Sandbox Code Playgroud)

scala variable-assignment println for-comprehension

29
推荐指数
2
解决办法
1万
查看次数

有没有办法在for comprehension中声明一个隐含的val?

我有一些代码嵌套调用flatMap,如下所示:

foo.flatMap(implicit f => bar(123).flatMap(b =>
  /* and so on... implicit f is still in scope here.*/
))
Run Code Online (Sandbox Code Playgroud)

通常,人们会将其写为理解,这使得代码更具可读性:

for {
  f <- foo
  b <- bar(123)
  /* yet more method calls that need f as an implicit parameter*/
}
Run Code Online (Sandbox Code Playgroud)

但我需要f暗示,我不认为有办法用于理解.在那儿?当然我可以明确地传递f,但这意味着再见DSL.我对Scala 2.9和2.10的答案感兴趣.

为了清楚起见,我想做这样的事情,但它不会编译:

for {
  implicit f <- foo
  b <- bar(123) //bar takes implicit argument
  /* yet more method calls that need f as an implicit parameter*/
}
Run Code Online (Sandbox Code Playgroud)

编辑:也许一个功能请求是一个好主意?

EDIT2:这应该适用于所有可以用于理解的类型,因此不仅仅是通常的集合类型,如ListSeq,还有Future …

scala implicit for-comprehension scala-2.9 scala-2.10

27
推荐指数
3
解决办法
2491
查看次数

获得Scala的desugared部分/理解表达式?

有没有人知道在实际尝试在REPL(或编译器)中编译之前如何获取(仅Scala部分)desgoared for for/comprehension表达式?

到目前为止,我唯一发现的是编译器"-print"标志,但它为您提供了完整的Scala转换...

scala syntactic-sugar for-comprehension

25
推荐指数
5
解决办法
8372
查看次数

Scala 2.10.1中的新的desugaring行为

假设我有这个monadic类:

case class Foo[A](xs: List[A]) {
  def map[B](f: A => B) = Foo(xs map f)
  def flatMap[B](f: A => Foo[B]) = Foo(xs flatMap f.andThen(_.xs))
  def withFilter(p: A => Boolean) = {
    println("Filtering!")
    Foo(xs filter p)
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是2.10.0 REPL会话:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
res0: Foo[Int] = Foo(List(1))
Run Code Online (Sandbox Code Playgroud)

这与2.10.1中的情况相同:

scala> for { (a, b) <- Foo(List(1 -> "x")) } yield a
Filtering!
res0: Foo[Int] = Foo(List(1))
Run Code Online (Sandbox Code Playgroud)

这对我来说是完全出乎意料的,并且在过滤需要额外约束(例如Scalaz \/EitherT)的情况下会导致特别混乱的错误.

我无法在2.10.1发行说明中 …

syntax monads filtering scala for-comprehension

24
推荐指数
1
解决办法
545
查看次数