2017-06-30 3 views
2

Wenn ich eine Suche nach einem Problembereich durchführen wollte und verschiedene Zustände verfolgen wollte, die ein Knoten bereits besucht hat, I several options to do it depending on the constraints of those states. Jedoch; Gibt es eine Möglichkeit, eine Funktion oder eine andere zu senden, abhängig von der Einschränkung der Zustände, die der Benutzer als Eingabe verwendet? wenn ich zum Beispiel:Haskell typeclasses in einer Funktion überprüfen

data Node a = Node { state :: a, cost :: Double } 

Und ich wollte auf einem Problem a eine Suche durchzuführen, ist es eine Möglichkeit, ich überprüfen könnte, wenn aEq ist, Ord oder Hashable und dann eine andere Art der Suche nennen? In Pseudo-Code, so etwas wie:

search :: Eq a => Problem a -> Node a 
search [email protected](... initial ...) -- Where initial is a State of type a 
    | (Hashable initial) = searchHash problem 
    | (Ord initial)  = searchOrd problem 
    | otherwise   = searchEq problem 

bin mir bewusst, dass ich nur der Benutzer eine search oder eine andere, je nach dem eigenen Gebrauch wählen lassen könnte; aber in der Lage zu sein, etwas zu tun, könnte für mich sehr praktisch sein, da die Suche nicht wirklich einer der Benutzerendpunkte als solcher ist (ein Beispiel könnte eine Funktion bfs sein, die search mit einigen Parametern anruft, damit sie sich wie ein Breitester verhält Suche).

+0

Alle Typinformationen werden während der Kompilierung gelöscht: Zur Laufzeit werden Werte nicht im Speicher mit ihren Typen markiert, noch wird eine Darstellung aller Typklasseninstanzen angezeigt. Dies macht solche Überprüfungen unmöglich. Wenn diese Information benötigt wird, muss der Programmierer explizit darum bitten, sie herum zu halten, z. wie Daniel Wagner unten mit einer benutzerdefinierten Klasse. – chi

Antwort

2

Nein, das geht nicht. Allerdings könnten Sie Ihre eigene Klasse machen:

class Memorable a where 
    type Memory a 
    remember :: a -> Memory a -> Memory a 
    known :: a -> Memory a -> Bool 

Instantiate diese Klasse für ein paar Basistypen, und einige Standardimplementierungen für Leute hinzufügen, die neue Instanzen hinzufügen möchten, z.B.

-- suitable implementations of Memorable methods and type families for hashable things 
type HashMemory = Data.HashSet.HashSet 
hashRemember = Data.HashSet.insert 
hashKnown = Data.HashSet.member 

-- suitable implementations for orderable things 
type OrdMemory = Data.Set.Set 
ordRemember = Data.Set.insert 
ordKnown = Data.Set.member 

-- suitable implementations for merely equatable things 
type EqMemory = Prelude.[] 
eqRemember = (Prelude.:) 
eqKnown = Prelude.elem 
+0

Ich bin mir nicht sicher, ob ich es verstehe: Ich weiß immer noch nicht, wie ich eine Implementierung der 'Memorable'-Klasse von etwas als' Eq a' machen soll, was mich verallgemeinern würde. Ist etwas wie 'instance Memorable (Eq a => a) wo möglich? –

+0

@DiegoVicente Wenn das möglich wäre, würden Sie die Typklasse "Memorable" nicht benötigen. 'Eq' enthält einfach nicht genügend Informationen, um die gewünschten Überprüfungen durchzuführen. – chi

+0

@DiegoVicente Nein, das ist nicht möglich (gut, das ist es; aber dann können Sie keine anderen Instanzen haben). Sie müssen z.B. 'instance Memorable Int, wo der Typ Speicher Int = EqMemory Int; erinnere dich = eqRemember; ================================================================================================================ Ja, das bedeutet, du musst alle Instanz-Deklarationen duplizieren, die bereits für 'Ord',' Hashable' und 'Eq' existieren - und aus diesem Grund wählen die meisten Leute entweder' Ord' oder 'Hashable' und laufen damit . –

Verwandte Themen