Function1 和 Reader Monad 的关系

Posted

技术标签:

【中文标题】Function1 和 Reader Monad 的关系【英文标题】:Relation between Function1 and Reader Monad 【发布时间】:2021-01-18 09:24:05 【问题描述】:

虽然我了解 reader monad 的实现,但我在下面给出了 2 种最突出的实现方式:

 case class Reader[R, A](run: R => A)
 def readerMonad[R] = new Monad[(type f[x] = Reader[R,x])#f] 
    def unit[A](a: => A): Reader[R, A] = Reader(_ => a)
    override def flatMap[A,B](st: Reader[R, A])(f: A => Reader[R, B]): Reader[R, B] =
      Reader(r => f(st.run(r)).run(r))
  

或更简单地说:

case class Reader[R, A](run: R => A) 

def map[B](f: A => B): Reader[R, B] =
    Reader(r => f(run(r)))

  def flatMap[B](f: A => Reader[R, B]): Reader[R, B] =
    Reader(r => f(run(r)).run(r))

 

我想知道 Reader Monad 和 Function1 之间是否存在内在关系。我一直在准备这里和那里的评论暗示这一点。根据定义,Reader 是 Function1 monad 吗?

我不这么认为。但我想围绕这个概念展开思考。

当函数的类型为 1 时,对函数进行排序意味着什么?

也就是说,您获取一个函数并应用一个返回相同类型函数的函数。我确实认为 Reader 是一种特定的技术,与函数是函数 1 的事实无关。通过线程化环境只是一种选择,如果我们愿意,可以使用 FunctionN 来完成。

只是一种直觉。

编辑

以下是在 Scala 中进行 FP 编程的练习:

Hard: To cement your understanding of monads, 
give a monad instance for the following type, 
and explain what it means. 
What are its primitive operations? 
What is the action of flatMap? ......

case class Reader[R, A](run: R => A)

object Reader 
  def readerMonad[R] = new Monad[(type f[x] = Reader[R,x])#f] 
    def unit[A](a: => A): Reader[R,A]
    def flatMap[A,B](st: Reader[R,A])(f: A => Reader[R,B]): Reader[R,B]
  
”

以及让我不满意的部分答案

// The action of Reader's `flatMap` is to pass the `r` argument along to both the
// outer Reader and also to the result of `f`, the inner Reader. Similar to how
// `State` passes along a state, except that in `Reader` the "state" is read-only.

我明白这一点,因为我可以阅读代码。我认为这种解释不足以清楚地回答练习的问题。我一直在寻找比代码功能的简单描述更笼统的东西。

例如,固定类型 R 意味着什么。链接计算返回作为具有相同输入参数类型的效果函数的计算意味着什么?

【问题讨论】:

所以 Reader monad 通常被称为依赖注入机制。因此,例如假设您有三个操作。第一个返回所有用户,第二个返回每个用户的城市,第三个返回每个城市的国家。你想计算每个国家的用户数量。但是,所有这些操作也需要连接到数据库。因此,您可能会忘记该细节,而是让它们将读取器从数据库连接返回到某些东西。因此,您可以编写所有这些操作而忘记数据库连接,直到运行。 【参考方案1】:

Reader[R, A]R => A 的包装器(因此可以在类内部定义方法,而不是作为函数的扩展方法)。函数f 可以包装到阅读器Reader(f),阅读器r 可以解包装到函数r.run。所以Reader[R, A]R => A 是一个同构。

Reader[R, ?] 有一个类型为 Monad 的实例。

R => ? 有一个类型为 Monad 的实例。

【讨论】:

这是什么意思:(所以方法可以在类内部定义,而不是作为函数的扩展方法)。 @MaatDeamon 函数没有mapflatMap。您可以将它们定义为Function1 的扩展方法或Reader 类中的普通方法。 让我这样问,function1有什么特别之处,它作为一个monad绑定了链中每个函数的参数 @MaatDeamon 现在确定你的问题是什么,想改写吗? 我想我正处于那种可能并不那么复杂的事情让你感到困惑的地步,以至于很难清楚地表达出什么是令人困惑的。我对这样的想法感到不舒服,因为 Function1 是 Function1,如果你在它上面定义一个单子行为,“它恰好给你一个读者模式”。例如,我想知道 flatMap 在 function1 上的行为是因为它是 Function1,还是因为我们决定以这种方式实现它,因为我们提前新了我们想要的东西

以上是关于Function1 和 Reader Monad 的关系的主要内容,如果未能解决你的问题,请参考以下文章

[Functional Programming] Reader with Async ADT

中间件单子?

不能以“读者”作为字段“强制”数据类型

`State#` 的规范

Monad的重点

monad 的例子在哪里? [复制]