Scala 如何多次调用“flatMap”自以为是的方式 问题:
当玩玩具示例-位置时,骑士可以从某个位置开始移动Scala 如何多次调用“flatMap”自以为是的方式 问题:,scala,functional-programming,flatmap,Scala,Functional Programming,Flatmap,当玩玩具示例-位置时,骑士可以从某个位置开始移动n步,然后到达棋盘上x-我想知道是否存在更干净的解决方案(在简洁性和功能编程的意义上) 执行flatMap(暂时忽略过滤器)一定次数(每次移动一次) 有一种(甚至)更像FP的编码方式 我试过的 一个简单的递归变量移动(…) 使用函数组合的变体move2(…) 代码 问题: 为什么要像阿尔瓦罗建议的那样使用Scalaz和Kleisli?(不是指责备,我想要争论;) 是否可能有更优雅的解决方案 不知道是否还有FP,但这里有一个版本使用scal
n
步,然后到达棋盘上x
-我想知道是否存在更干净的解决方案(在简洁性和功能编程的意义上)
- 执行
(暂时忽略flatMap
)一定次数(每次移动一次)过滤器
- 有一种(甚至)更像FP的编码方式
- 一个简单的递归变量移动(…)
- 使用函数组合的变体
move2(…)
- 为什么要像阿尔瓦罗建议的那样使用Scalaz和
?(不是指责备,我想要争论;)Kleisli
- 是否可能有更优雅的解决方案
=>
import scalaz.Kleisli
import scalaz.syntax.kleisli._
import scalaz.std.list._
def move3 (startPos: Position, steps: Int, chessboard: Chessboard) : Set[Position] = {
val validMove = Kleisli {a: Position => knightMoves(a).filter(chessboard.positionOnBoard).toList}
List.fill(steps)(validMove).reduce(_ >=> _)(startPos).toSet
}
必须使用List,因为Set没有绑定实例
更新:删除了
step-1
,这是我试用的上一个版本的遗留版本。看起来更适合我老实说,这并不是代码审查。首先,方法的结构得到了很好的定义。第二,给出了一个完整的运行示例。中心问题(如标题中强调的)是如何以最简洁和功能性的编程方式多次执行flatMap
。谢谢你的理解!我想代码审查的目的不是让它工作,而是简化和美化代码列表。填充(步骤1)
似乎不正确。至少对于Scala来说,它必须是List.fill(step)
。其次,你能解释一下为什么需要KleislI
?(见我的编辑方法2b))@MartinSenne Kleisli在我看来(不是专家),当我们知道第一个单子产生的值直接进入下一个单子时,似乎更合适、更简洁。对于flatMap
,情况并非总是如此,它可能被忽略或被其他东西取代。
def move2b(startPos: Position, steps: Int, chessboard: Chessboard) : Set[Position] = {
val nextFnc : Set[Position] => Set[Position] = {
_.flatMap( knightMoves(_).filter( chessboard.positionOnBoard(_)) )
}
List.fill(steps)(nextFnc).reduce(_ compose _)(Set(startPos))
}
import scalaz.Kleisli
import scalaz.syntax.kleisli._
import scalaz.std.list._
def move3 (startPos: Position, steps: Int, chessboard: Chessboard) : Set[Position] = {
val validMove = Kleisli {a: Position => knightMoves(a).filter(chessboard.positionOnBoard).toList}
List.fill(steps)(validMove).reduce(_ >=> _)(startPos).toSet
}