2016-07-25 5 views
1

Angenommen, ich habe eine ADT wie diese bekommen:Würden Sie in diesem Fall eine Typklasse verwenden?

sealed trait A extends Product with Serializable 
object A { 
    case class A1() extends A 
    case class A2() extends A 
    case class A3() extends A 
    case class A4() extends A 
} 

Angenommen, auch habe ich eine trait AFoo wie folgt aus:

type Foo = ... 
trait AFoo { def asFoo(a: A): Foo } 

Jetzt muss ich für AFoo zwei verschiedene Implementierungen bieten. Also schreibe ich etwas wie folgt aus:

abstract class AFooSupport extends AFoo { 

    protected def asFoo1(a1: A1): Foo 
    protected def asFoo2(a2: A2): Foo 
    protected def asFoo3(a3: A3): Foo 
    protected def asFoo4(a4: A4): Foo 

    def asFoo(a: A) = a match { 
    case a1: A1 => asFoo1(a1) 
    case a2: A2 => asFoo2(a2) 
    case a3: A3 => asFoo3(a3) 
    case a4: A4 => asFoo4(a4) 
    } 
} 

class AFoo1 extends AFooSupport { 
    // implement asFoo1, asFoo2, asFoo3, asFoo4 
} 

class AFoo2 extends AFooSupport { 
    // implement asFoo1, asFoo2, asFoo3, asFoo4 
} 

Dieser Ansatz wird wahrscheinlich funktionieren, aber ich frage mich, ob es einen besseren Weg, es zu tun. Würden Sie in diesem Fall eine Typklasse verwenden?

+2

Benötigen Sie mehrere Implementierungen von 'asFoo'? Die Verwendung einer Typklasse für eine Operation, die nur für einen einzelnen ADT gilt, erscheint ungerade. Wenn Sie das Matching wirklich abstrahieren wollen, erscheint eine Falte vernünftiger. –

+0

Ich brauche nur eine Implementierung von 'asFoo'. Werde die 'fold' versuchen, danke. – Michael

Antwort

1

Es gibt nur eine Funktion (A => Foo) für konkrete Klassen mit verschiedenen Implementierungen. Ich sehe hier keinen großen Vorteil der Verwendung einer Typklasse. Ich würde anfangen, eine Typklasse zu betrachten, wenn eines der Argumente generisch ist.

Wie in den Kommentaren vorgeschlagen könnte ein Muster in fold passende extrahieren

def fold[F](a: A)(f1: A1 => F, ..., f4: A4 => F): F = a match { 
    case a1: A1 => f1(a1) 
    ... 
} 

und erforderlichen Funktionen implementieren:

def aFoo(a: A): Foo = fold(a)(afoo1, afoo2, afoo3, afoo4) 
def afoo1(a: A1): Foo = ... 
... 
def afoo4(a: A4): Foo = ... 

def bFoo(a: A): Foo = fold(a)(bfoo1, bfoo2, bfoo3, bfoo4) 
... 
def bfoo4(a: A4): Foo = ... 

Aber Ihr AFooSupport ist schon irgendwie eine Falte mit Vererbung statt Zusammensetzung umgesetzt.

+2

Beachten Sie, dass für die "falte" jede Argumentfunktion nicht "A1", usw. als Argument annehmen muss - "A1", usw. haben keine Mitglieder, so dass die zu faltenden Argumente "(f1: => F, f2: => F, ...) '. –

-2

Auf den ersten Blick scheint es, als könnten Sie Generika als Lösung verwenden oder Ihr Problem mit der Vererbung lösen.

Verwandte Themen