10

在观看了 John De Goes 的“FP to the Max”(https://www.youtube.com/watch?v=sxudIMiOo68)之后,我想知道以无标记最终模式编写 FP 程序的方法。

假设我有一些用于建模副作用的类型类(以他的Console例子):

trait Console[F[_]] {
  def putStrLn(str: String): F[Unit]
  def getStrLn: F[String]
}

你会怎么依赖Console

隐式

就像他的视频中展示的那样:

def inputLength[F[_]: Functor: Console]: F[Int] =
  Console[F].getStrLn.map(_.length)

优点:函数签名很干净,您可以从 typeclass 自动派生中受益

明确地

通过将实例直接传递给函数:

def inputLength[F[_]: Functor](console: Console[F]): F[Int] =
  console.getStrLn.map(_.length)

优点:这使您可以根据需要明确连接依赖项,并且感觉不那么“神奇”

不确定编写此功能的最佳/最惯用的方法是什么,不胜感激。

谢谢!

4

1 回答 1

5

当您通过隐式参数依赖类型类实例时,您可以确定一件事,那就是您可以在编译时确定类型类的实例(除非您明确提供它,哪种方式违背了目的,然后我们回到示例 2)。相反,如果您无法在编译时确定该类的实例,例如当您依赖配置参数来确定实例类型时,那么任何类型的隐式参数都不再适合。

因此,根据我自己的观点和喜好,我想说的是,只要可以在编译时确定实例并让编译器找出接线,就这样做,因为正如您所说,您会从中受益匪浅,例如在可用时享受自动类型类派生的能力。

“神奇”的论点虽然可以理解,但表明无论谁说这仍然需要使用他正在编程的语言,并且需要学习事情是如何工作的,这完全可以,但不是不使用 typeclass 的充分理由通过隐式参数的实例。

于 2019-01-27T09:14:40.120 回答