Questo è il mio secondo tentativo per definire il problema, non riesco a capirlo.Typeclasses ed ereditarietà in scalaz
Voglio essere in grado di definire un tipo algebrico e definire su di esso un semplice typeclass, diciamo Show
. In Haskell faccio:
data Tree a = EmptyTree | Node a deriving (Show)
Ora, se di tipo I EmptyTree
- Haskell può mostrare esso, quindi appartiene alla Show
.
Ora sto cercando di fare lo stesso a Scala:
sealed abstract class Tree[+T]
case object EmptyTree extends Tree[Nothing]
case class Node[T](value: T) extends Tree[T]
Poi mi definiscono Show
intorno ad esso:
implicit def show[T] = Show.showA[Tree[T]]
posso fare println((EmptyTree : Tree[Int]).show)
. Ma non posso fare println(EmptyTree.show)
(risposta è value show is not a member of object EmptyTree
)
devo scrivere supplementari:
implicit class MyShowOps[A, +T <: Tree[A]](t: T) {
def showMy(implicit ev: Show[Tree[A]]): String = ev.shows(t)
}
E solo allora posso fare println(EmptyTree.showMy)
E ancora non suona corretto, credo o sto cercando di fare una cosa sbagliata e non dovrei applicare Show
in questo modo e dovrei usare la mia costruzione solo come Tree[T]
o mi manca una costruzione corretta da Scalaz.
Ho visto modelli come 'val emptyTree: Tree [Nothing] ..' in fonti scalaz, ma non riuscivo a capire perché fosse fatto in quel modo. Ora è chiaro per me. C'è ancora qualcosa che non capisco, c'è qualche ragione particolare per cui in "ShowOps" di scalaz non è stato definito come ho fatto io? Sembra più semplice che dover definire i metodi di wrapper come 'emptyTree' e' node [T] ' – Archeg
Il modello di costruzione up-casting risolve molti di questi problemi su tutta la linea in un unico posto, mentre fornire le istanze per i sottotipi avrebbe un impatto su tonnellate di codice. In generale, Scalaz non si occupa del sottotipo (ad esempio la maggior parte delle classi di tipi sono invarianti e le istanze non sono fornite per i sottotipi). –