【发布时间】: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 通常被称为依赖注入机制。因此,例如假设您有三个操作。第一个返回所有用户,第二个返回每个用户的城市,第三个返回每个城市的国家。你想计算每个国家的用户数量。但是,所有这些操作也需要连接到数据库。因此,您可能会忘记该细节,而是让它们将读取器从数据库连接返回到某些东西。因此,您可以编写所有这些操作而忘记数据库连接,直到运行。
标签: scala functional-programming