无标记最终类型类型依赖

时间:2019-01-27 07:12:47

标签: scala functional-programming tagless-final

看完约翰·德·戈斯(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)

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

不确定哪种最佳或最惯用的方式编写此功能,将不胜感激您的意见。

谢谢!

1 个答案:

答案 0 :(得分:5)

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

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

“不可思议”的论点虽然可以理解,但表明有人说他仍然有用他正在编程的语言行进的里程,并且需要学习事物的工作原理,这完全可以,但还不够充分,理由是通过隐式参数使用类型类实例。