2016-12-12 5 views
2

Ich möchte diese schöne, saubere Art und Weise haben die Eigenschaften eines Objekts mit Funktionen und Mustervergleich zu beschreiben:Funktionsdeklaration über Pattern-Matching auf mehreren Leitungen

data Animal = Cat | Dog | Cow 

isBig :: Animal -> Bool 
isLoyal :: Animal -> Bool 
-- many more possible properties, including complicated non-bools, methods, and whatnot 


--- Describing Cat 

isBig Cat = False 
isLoyal Cat = False 
--- more properties 


--- Describing Dog 

isBig Dog = False 
isLoyal Dog = True 
--- more properties 


--- Describing Cow 

isBig Cow = True 
isLoyal Cow = False 
--- more properties 

Dies ist jedoch eine Fehlermeldung über mehrere Erklärungen gibt. Offensichtlich muss die Funktionsdefinition über den Mustervergleich in aufeinanderfolgenden Zeilen erfolgen.

Ist es bezeichnend, dass mein Ansatz falsch ist, un-Haskell-like? Oder ist es nur ein Fehler in der Sprache? Oder verstehe ich etwas falsch?

+1

In diesem Fall macht es keinen Sinn - oder ich hätte es in meiner Antwort erwähnt - aber vielleicht ist der Fall in Ihrer Frage eine Vereinfachung dessen, was Sie tatsächlich versuchen zu tun. Wenn das der Fall ist, könnten Sie in Betracht ziehen, eine Typklasse zu erstellen, die 'isBig',' isLoyal' usw. enthält und _types_ 'Dog',' Cat' und 'Cow' erzeugt, die diese Klasse implementieren. Dies ist jedoch ziemlich anders: Klassen sind offen, im Gegensatz zu Typen. –

Antwort

5

Es ist weder ein Fehler in der Sprache noch ein Hinweis darauf, dass Ihr Ansatz falsch ist. Es ist lediglich eine syntaktische Beschränkung, die als Teil einer fiesen Designentscheidung eingeführt wurde, die auf die eine oder andere Weise getroffen werden musste. Die Anziehungskraft der Einschränkung besteht darin, dass es bedeutet, dass man beim Lesen von Code nicht fürchten muss, dass sie einen Teil der Definition eines Wertes verpasst haben, weil sie weit über die aktuelle Datei verteilt ist. Es verhindert jedoch einige perfekt logische Arten der Code-Organisation, einschließlich der, die Sie gerade verwenden.

Was für eine Schande, dass wir nicht beide haben können!

Man könnte prüfen, so etwas wie dies zu tun:

data Stats = Stats 
    { isBig :: Bool 
    , isLoyal :: Bool 
    , -- ... 
    } 

stats :: Animal -> Stats 
stats Cat = Stats 
    { isBig = False 
    , isLoyal = False 
    } 
+0

Was wäre eine gute Möglichkeit, ein Stück Code wie dieses Beispiel zu organisieren? – user2649762

+0

@ user2649762 Ich habe einen Gedanken zu einem Ansatz hinzugefügt, den Sie mögen könnten. –

+0

Danke, noch eine Sache. Es gibt viele Eigenschaften, und die meisten sind nicht für alle Tiere definiert. Ich hatte etwas wie 'isLoyal _ = False; isBig _ = False "am Ende der Datei, so dass, wenn ich keine bestimmte Eigenschaft für ein Animal definiert habe, diese einfach auf einen Wert gesetzt wird. Wie kann ich das mit Ihrem Ansatz umsetzen? – user2649762

2

Zitiert Section 4.4.3.1 of the Haskell Report:

4.4.3.1 Funktions Bindungen

Eine Funktion auf eine Funktionswert bindet eine variable Bindung. Die allgemeine Form einer Funktion für variablen x Bindung:

[Spezifikation zur Syntax von Funktions Bindungen, für das Mehrfach Klausel Szenario.]

beachte, dass alle Klauseln Definition eine Funktion zusammenhängend sein müssen, und die Anzahl Muster in jeder Klausel müssen identisch sein. [...]

Die Beschränkung, die Sie bemerkt haben, ist, dass "alle Klauseln, die eine Funktion definieren, zusammenhängend sein müssen". Daniel Wagners Antwort geht auf die mutmaßlichen Gründe für diese Designentscheidung ein. Ich würde insbesondere betonen, dass das Vergessen einer Klausel, die einem der Konstruktoren eines Typs entspricht, ein ziemlich gefährlicher Fehler ist, der leichter zu begehen wäre, wenn es möglich wäre, die Klauseln in der Art und Weise zu unterbrechen, die Sie vorschlagen Ein Animal wird voraussichtlich alle drei Möglichkeiten behandeln).

Verwandte Themen