2015-07-07 14 views
6

Dati i seguenti implementazioni di f a Haskell e Scala:.Typeclasses a Haskell v Scala

Prelude> let f x y = x == y 
Prelude> :t f 
f :: Eq a => a -> a -> Bool 

Scala:

scala> trait Equal[A] { def ===(x: A, y: A): Boolean } 
defined trait Equal 

scala> implicit val equalsInt = new Equal[Int] { 
    | def ===(x: Int, y: Int):Boolean = (x == y) 
    | } 
equalsInt: Equal[Int] = [email protected] 

scala> def f[A : Equal](x: A, y: A): Boolean = 
    | implicitly[Equal[A]].===(x, y) 
f: [A](x: A, y: A)(implicit evidence$1: Equal[A])Boolean 

scala> f(10, 20) 
res0: Boolean = false 

scala> f(55, 55) 
res1: Boolean = true 

Guardando questo video, Typeclasses v. the World, la mia comprensione incompleta è che la risoluzione implicita di Scala , vale a dire come raggiunge classi di tipi, è suscettibile di risoluzione errata/incoerente di impliciti. Ma Haskell non usa impliciti per i typeclass, quindi non c'è alcun problema in Haskell.

Considerando le differenze tra le implementazioni di typeclass di Scala e Haskell, quali sono i possibili problemi della precedente definizione di f in Scala che sono assenti da Haskell?

risposta

5

Un problema che la versione di Scala può avere che la versione di Haskell non può, è che in Scala è possibile definire più di un'istanza di Equal[Int] nell'ambito quando il macchinario di risoluzione implicita sta cercando di trovare un'istanza. Che è quando è possibile ottenere un errore del tipo:

<console>:12: error: ambiguous implicit values: 
both value EqualInt1 of type => Equal[Int] 
and value EqualInt2 of type => Equal[Int] 
match expected type Equal[Int] 
       f(1, 2) 
      ^

Aggiornamento. Come sottolinea Carl in un commento, un altro problema è che è possibile avere istanze diverse nell'ambito in diversi punti del codice, così che chiamare f potrebbe utilizzare queste diverse istanze con risultati molto diversi e senza errori di compilazione o di runtime.

+3

Più di quello .. È possibile avere impliciti diversi nell'ambito in diversi contesti senza errori. Quindi puoi costruire un valore di 'Set' con un tipo di uguaglianza in ambito, quindi usarlo con un diverso tipo di uguaglianza in ambito, portando a risultati inconsistenti e buggati. La mera uguaglianza è un po 'debole per dimostrarlo, ma qualcosa come "Ord" di Haskell è sufficiente con gli alberi di ricerca binari. – Carl