2017-10-07 5 views
2

ich Haskell neu bin so kann es offensichtlich sein, aber ich habe Prolog ausgiebig so bin ich über diese perplex ...Haskell Tupel nicht mit Funktionsargument passende

Wenn GHCi mit, habe ich die folgende Funktion (1):

Prelude> let find k t = head [v | (k',v) <- t, k == k'] -- Definiton of find 
find :: Eq a1 => a1 -> [(a1, a)] -> a 

Prelude> find 2 [(1,11),(2,22)] -- Invocation of find 
22 

Welche wird erwartet. Ich habe dann versucht, die k‘aus der Definition zu entfernen:

Prelude> let find2 k t = head [v | (k,v) <- t] 
find2 :: t -> [(t1, a)] -> a 

Prelude> find2 2 [(1,11),(2,22)] 
11 

Ich war dann sehr überrascht, um den Wert zu sehen 2 angepasst tatsächlich mit 1. Nur um sicherzugehen ich nicht das Unmögliche hatte gehofft, dass ich auch versuchen, die folgenden, um bestätigt, dass eine teilweise Übereinstimmung möglich ist, in Haskell, die aussieht wie es tatsächlich der Fall ist:

Prelude> head [v | (2,v) <- [(1,11),(2,22)]] 
22 

Ich habe auch bemerkt einen Unterschied in den Funktionsdeklarationen. Ich fügte die erforderlichen Informationen hinzu, so dass beide Deklarationen für find und find2 genau gleich aussehen. Aber das Ergebnis ist immer noch kaputt (2,_)(1,11) matchnig:

Prelude> let find2 :: Eq a1 => a1 -> [(a1, a)] -> a; find2 k t = head [v | (k,v) <- t] 
find2 :: Eq a1 => a1 -> [(a1, a)] -> a 

Prelude> find2 2 [(1,11),(2,22)] 
11 

Wie kann 2 werden passend 1 von jedem bedeuten?

(1) Die obige Funktion kommt aus dem ausgezeichneten Buch „Programming in Haskell“ S.93

+4

Kurz gesagt: Prolog tut Vereinigung , Haskell macht nur Mustervergleiche. – chi

+4

Langweiliger praktischer Rat: die Verwendung von "-Wall" wird sehr hilfreich sein, während Sie lernen (und auch um Probleme in echtem Code zu finden) – jberryman

Antwort

11

Ja, passende Haskell Mustern grundsätzlich verschieden von Prolog Mustervergleich ist.

In Haskell bezieht sich eine Variable in einem Muster auf eine frische Variable, die durch die Übereinstimmung gebunden wird, niemals eine vorhandene Variable, die angepasst werden muss. Also, der Ausdruck:

let x = 5 in case (1,2) of (x,y) -> "matched!" -- gives "matched!" 

wird immer zu "abgestimmt" ausgewertet werden. Das ist, weil die x in (x,y) frisch zu 1 gebunden wird, nicht im Vergleich mit dem Wert der „bestehenden“, äußerte Definition von x, wie Sie hier sehen können:

let x = 5 in case (1,2) of (x,y) -> x  -- gives "1" 

Das Verhalten für numerische Konstanten unterscheiden:

case (1,2) of (5,y) -> "matched!" -- match fails 

und für andere Konstrukteure:

case (True,2) of (False,y) -> "match!" -- match fails 

, die nicht "re-bound" sind sondern muss übereinstimmen, damit die Musterübereinstimmung erfolgreich ist. Dies ist einer von vielen Gründen, warum alphanumerische Konstruktoren mit Großbuchstaben beginnen: Andernfalls wäre es sehr schwierig zu bestimmen, ob ein Muster mit einem vorhandenen Konstruktor übereinstimmt oder sich an eine neue Variable bindet.

Dieses zu Muster passt in jedem Kontext gilt, ob es case-Ausdrücke wie oben oder Funktionsdefinitionen wie folgt ist:

let x = 5 
f x = "hi"  -- defines `f` for any `x`, not just `f 5` 

oder Listenkomprehensionen wie Ihr Beispiel.In dem Ausdruck:

[v | (k,v) <- [(1,2),(3,4)]] -- gives [(1,2),(3,4)] 

die Variablen k und v wird immer frisch sein, wird so binden sich an eine der Tupeln trotz keine äußeren bestehenden Definitionen von k oder v. Wenn Sie Warnungen mit -Wall (speziell -Wname-shadowing) aktivieren, werden Sie auf die schattierte Bindung hingewiesen. Wenn Sie k mit einer konstanten (oder einem anderen Konstruktor) ersetzen, verhält es sich anders:

[v | (3,v) <- [(1,2),(3,4)]] -- only gives [(3,4)] 

Sie können es nicht, aber das ist nur die Art und Weise Haskell funktioniert.

+0

"Sonst wäre es ungeheuer schwierig zu bestimmen, ob" -> Meh, das ist nur der Gültigkeitsbereich . Scope-aware Syntax Highlighting kann damit gut umgehen (vgl. ZB Agda) – gallais

0

Danke für Ihre Hilfe! Nach einigen Suchen fand ich auch diese Antwort hilfreich: How can I re-assign a variable in a function in Haskell?

Eine neue Variable mit dem gleichen Namen wird erstellt, die die vorherige Schatten. Aber die erste Variable weiterhin in einigen Fällen existieren und noch zugänglich sein ...

So in der Tat ist dies weit von Prolog und ja das folgende Flag ist der wertvolle Hilfe:

Prelude> :set -fwarn-name-shadowing