В чем разница между неявным def и неявным val?

#scala #scala-cats

#scala #scala-кошки

Вопрос:

У меня есть следующий код, который я не могу понять, в чем разница:

   implicit def boxPrintable[A](implicit p: Printable[A]) =
    p.contramap[Box[A]](_.value)

  implicit val stringPrintable: Printable[String] =
    new Printable[String] {
      def format(value: String): String =
        "Foo " | | value | | " Too"
    }  
  

Оба являются реализацией для типов. Вопрос в том, когда использовать def и когда использовать val ?

Весь код:

 package com.sweetsoft

import cats.instances.string._
import cats.syntax.semigroup._
import cats.Contravariant
import cats.Show
import cats.instances.string._

final case class Box[A](value: A)

trait Printable[A] {
  self =>

  def format(value: A): String

  def contramap[B](func: B => A): Printable[B] =
    new Printable[B] {
      override def format(value: B): String = self.format(func(value))
    }
}


object Main {

  val showString = Show[String]

  implicit def boxPrintable[A](implicit p: Printable[A]) =
    p.contramap[Box[A]](_.value)

  implicit val stringPrintable: Printable[String] =
    new Printable[String] {
      def format(value: String): String =
        "Foo " | | value | | " Too"
    }

  implicit val booleanPrintable: Printable[Boolean] =
    new Printable[Boolean] {
      def format(value: Boolean): String =
        if (value) "yes" else "no"
    }

  def main(args: Array[String]): Unit = {
    println(format("Hello"))
    //println(format(Box("hello world")))
  }

  def format[A](value: A)(implicit p: Printable[A]): String =
    p.format(value)

}
  

Комментарии:

1. Здесь нет ничего implicit специфичного: соответствующие соображения точно такие же, как val vs. def в любом другом контексте.

Ответ №1:

Ваш boxPrintable принимает параметр типа A и аргумент значения типа Printable[A] , поэтому это должно быть def .

String это один конкретный тип, поэтому stringPrintable вообще не принимает параметров, это просто константа, поэтому вы можете определить ее как val .

Больше ничего.

Ответ №2:

def вычисляется при каждом запросе.

val вычисляется при создании класса.

В вашем примере вам нужен a, def как только у него появятся параметры, которые невозможны с val s.