List of classes implementing a specific type

I would like to define Listelements that implement the general type of a class. For instance.

  trait Show[A] {
    def show(a: A): String
  }
  implicit val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int): String = s"int $int"
  }
  implicit val stringCanShow: Show[String] = new Show[String] {
    def show(str: String): String = str
  }

The problem is how to define a list = List(1, "abc")to ensure that the instance Showfor these values ​​is in scope? Then I would like to display this list, for example list map {_.show}.

+4
source share
4 answers

I will first draw a solution, and then explain why a naive approach List[Any](1, "abc")cannot work.


what can you do

Define a wrapper class that can contain instances of a type Aalong with instances Show[A]:

case class Showable[A](a: A, showInst: Show[A]) {
  def show: String = showInst.show(a)
}

Define your list as List[Showable[_]]:

var showableList: List[Showable[_]] = Nil

, ( - ):

def addShowable[A: Show](a: A): Unit = {
  showableList ::= Showable[A](a, implicitly[Show[A]])
}

, ( ) :

implicit def asShowable[A](a: A)(implicit s: Show[A]): Showable[A] = 
  Showable(a, s)

( ):

val showableList = List[Showable[_]](1, "abc")

show:

showableList.map(_.show)

String.


val list: List[Any] = List(1, "abc", <showable3>, ..., <showableN>)

, show, Show.show show. , , , . List[Any], , Any, Show[T_1],..., Show[T_N]. " Free monad" .

+3

. , .

Shapeless , , , :

  • (HList)
  • HList.

(shapeless):

import shapeless.{HNil, Poly1, ::}

, . , .

val data : Int :: String :: HNil = 1 :: "hello" :: HNil

, , .

object Show extends Poly1 {
    implicit def atT[T: Show] = at[T] (implicitly[Show[T]].show)
}

Shapeless HList, show

val result : String :: String :: HNil = data.map(Show)

: @dk14 Show.

+4

, , List[Int, String] List[Any]. , , Int String, "", List. scala -, , Tuple:

val tuple = (1, "abc")
val result = List(implicitly[Show[Int]].show(tuple._1), implicitly[Show[Int]].show(tuple._2))

scala - map - .

, HList Shapeless: Int :: String :: HNil ( tuple (Int, String))

import shapeless._
import poly._


//show is a polymorphic function
//think of it as `T => String` or even `(Show[T], T) => String` 
object show extends Poly1 {
  implicit def atT[T: Show] = at[T](implicitly[Show[T]].show)
}

@ (1 :: "aaaa" :: HNil) map show
res8: String :: String :: HNil = "int 1" :: "aaaa" :: HNil

at[Int]/at[String] , @Steve Robinson.

P.S. . REPL , , :

curl -s https://raw.githubusercontent.com/milessabin/shapeless/master/scripts/try-shapeless.sh | bash    

:

  • , Tuple. , Int String - ( List[T]). Shapeless , .

  • - , implicit class Haskell, Haskell-like, Simulacrum .


, scala - , - :

trait Showable[T]{def value: T; def show: String}
class IntShow(val value: Int) extends Showable[Int]{..}
class StringShow(val value: String) extends Showable[String] {..}

val showables: List[Showable[_]] = List(new Showable(5), new Showable("aaa"))
showables.map(_.show)

:)

FP-:

sealed trait Showable
final case class ShowableInt(i: Int) extends Showable
final case class ShowableString(s: String) extends Showable

implicit class ShowableDispatch(s: Showable){
  def show = s match{ //use `-Xfatal-warnings` scalac option or http://www.wartremover.org/ to guarantee totality of this function
    case ShowableInt(i) => ...
    case ShowableString(s) => ...
  }
}

List(ShowableInt(5), ShowableString("aaa")).map(_.show)

( ad-hoc-), , Showable[_], Showable[Any]:

case class Showable[T](v: T, show: String)
def showable(i: Int) = Showable(i, s"int $i") 
def showable(s: String) = Showable(i, s) 
List(showable(5), showable("aaa")).map(_.show)
+4

Disclamer: , , typeclass


:

trait Showable{ def show(): String }

implicit class IntCanShow(int: Int) extends Showable {
  def show(): String = s"int $int"
}

implicit class StringCanShow(str: String) extends Showable {
  def show(): String = str
}

val l: List[Showable] = List(1,"asd")

Note that I changed the value of the Show to Showable, so that the implementing classes are used as a wrapper. That way, we can simply require that we want the displayed instances (and since these classes are implicit, the list entry is automatically completed)

0
source

Source: https://habr.com/ru/post/1694785/


All Articles