Reader monad有什么好处?

麦可

我已经阅读了有关monad博客文章Reader

该帖子确实很棒,并详细说明了该主题,但我不明白为什么Reader在这种情况下应该使用monad。

帖子说:假设有一个功能 query: String => Connection => ResultSet

def查询(sql:String)= conn:Connection => conn.createStatement.executeQuery(sql)

我们可以运行一些查询,如下所示:

def doSomeQueries(conn:Connection)= { 
  val rs1 = query(“ SELECT COUNT(*)FROM Foo”)(conn)
  val rs2 = query(“ SELECT COUNT(*)FROM Bar”)(conn)
  rs1.getInt(1 )+ rs2.getInt(1)
}

到目前为止还算不错,但是帖子建议改用Readermonad:

类Reader [E,A](运行:E => A){ 

  def map [B](f:A => B):Reader [E,B] =
    新Reader(е=> f(run(е)) )

  def flatMap [B](f:A => Reader [E,B]):Reader [E,B] = 
    new Reader(е=> f(run(е))。run(е))   
} 

val查询( sql:String):Reader [Connection,ResultSet] = 
  new Reader(conn => conn.createStatement.executeQuery(sql))

def doSomeQueries(conn:Connection)= for { 
  rs1 < -query (“ SELECT COUNT(*)FROM Foo “)
  rs2 <-查询(” SELECT COUNT(*)FROM Bar“”)
}产生rs1.getInt(1)+ rs2.getInt(1)

好的,我知道我不需要connection显式地遍历所有调用。所以呢 ?
为什么Readermonad解决方案比上一个更好?

更新:修复了def查询中的错字:=应该是=>此注释仅存在是因为SO坚持要求编辑长度必须至少为6个字符。所以我们开始。

特拉维斯·布朗(Travis Brown)

最重要的原因是,读者单子让你建立复杂的计算组成请考虑非阅读器示例中的以下行:

val rs1 = query("SELECT COUNT(*) FROM Foo")(conn)

我们conn手动传递的事实意味着这一行本身并没有真正的意义-只有在doSomeQueries提供方法的上下文中才能理解和推理这一行conn

通常这没什么问题-定义和使用局部变量(至少在val某种意义上)显然没有但是,有时候,从独立的可组合片段中构建计算更为方便(或出于其他原因而被期望),读者monad可以提供帮助。

query("SELECT COUNT(*) FROM Foo")在第二个示例中考虑假设我们知道是什么query,这是一个完全自包含的表达式-不需要像conn这样的变量需要通过某些封闭范围来绑定。这意味着您可以更加自信地重用和重构,并且在进行推理时没有太多东西可以挂起来。

再次,这不再是必需的-它很大程度上取决于样式。如果您决定尝试一下(我建议您这样做),您可能会很快发展出一些偏好和直觉,以了解哪些地方使您的代码更易懂,哪些地方没有让您的代码更易懂。

另一个优点是您可以使用ReaderT(或通过添加Reader到其他堆栈中)来组合不同种类的“效果” 不过,这一系列问题可能值得其提出自己的问题和答案。

最后一点:您可能希望自己doSomeQueries看起来像这样:

def doSomeQueries: Reader[Connection, Int] = for {
  rs1 <- query("SELECT COUNT(*) FROM Foo")
  rs2 <- query("SELECT COUNT(*) FROM Bar")
} yield rs1.getInt(1) + rs2.getInt(1)

或者,如果这确实是该行的结尾:

def doSomeQueries(conn: Connection) = (
  for {
    rs1 <- query("SELECT COUNT(*) FROM Foo")
    rs2 <- query("SELECT COUNT(*) FROM Bar")
  } yield rs1.getInt(1) + rs2.getInt(1)
).run(conn)

在您当前的版本中,您实际上并未使用conn

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章