看完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)
优点:这允许您根据自己的需求明确地连接依赖关系,并且感觉不那么"神奇">
不确定编写此函数的最佳/最惯用的方式是什么,请发表意见。
谢谢!
当您通过隐式参数依赖于typeclass实例时,有一件事是您可以确定的,那就是您可以在编译时确定您的typeclass的实例(除非您明确地提供它,否则这会破坏目的,然后我们回到示例2)。相反,如果不能在编译时确定该类的实例,例如,当您依赖配置参数来确定实例类型时,那么任何类型的隐式参数都不再适用。
因此,根据我自己的意见和喜好,我想说的是,无论何时,只要可以在编译时确定实例,并让编译器找出连接,都要这样做,因为正如您所说,您可以从中获得很多好处,例如在可用时享受自动类型类派生的能力。
"神奇"的论点虽然可以理解,但表明无论谁说这句话,在他编程的语言中仍然有相似之处,需要学习事物是如何工作的,这是完全可以的,但这并不是不通过隐式参数使用类型类实例的充分理由。