2017-02-08 2 views
-3

Ich versuche, eine Liste Verständnis zu verwenden, um den Median einer Liste zu finden, die immer drei ganze Zahlen mit der folgenden Funktion enthalten:Wie gibt ein Haskell-Listenverständnis ein Ergebnis aus, das eine ganze Zahl ist?

midNum set = [x | x <- set, x /= maximum set, x /= minimum set]!!0 

Dies allein gut genug funktioniert, wie im folgenden Beispiel:

ghci> midNum [1,2,3] 
2 

aber es bläst, wenn ich versuche, es mit meinen anderen Funktionen in Verbindung zu verwenden, in den folgenden Fehlern führt:

*** Exception: Prelude.!!: index too large 

Wenn ich entferne die ‚!! 0‘, der Compiler mir diese Nachricht gibt:

Triangle.hs:4:79: error: 
* Occurs check: cannot construct the infinite type: t ~ [t] 
* In the second argument of `(+)', namely 
    `squareOf (midNum triangle)' 
    In the second argument of `(==)', namely 
    `squareOf (minimum triangle) + squareOf (midNum triangle)' 
    In the expression: 
    squareOf (maximum triangle) 
    == squareOf (minimum triangle) + squareOf (midNum triangle) 
* Relevant bindings include 
    triangle :: [t] (bound at Triangle.hs:4:9) 
    isRight :: [t] -> Bool (bound at Triangle.hs:4:1) 
Failed, modules loaded: none. 

So sieht es aus, als ob die Funktion mir eine ganze Zahl ist zu geben, aber der Compiler eine Liste erwartet. In einer anderen Sprache würde ich tippen, um das zu beheben, aber ich bin mir nicht sicher, was ich in Haskell machen soll.

Dies ist auch im Wesentlichen mein erster Sprung in Haskell, also vergib mir, wenn die Antwort offensichtlich ist.

+2

Könnten Sie den Code hinzufügen, der zu einem Fehler führt? Ihr Beispiel sollte zu einer Liste mit einem Element ausgewertet werden. Ihr Beispiel wird nicht geprüft, wenn Sie 'Minimum' und' Maximum' anstelle von 'Min' und' Max' verwenden. – Lee

+0

Wenn Sie wissen, dass die Liste immer 3 Elemente lang ist und nur den Medianwert haben soll, verwenden Sie 'sort list !! 1? – jkeuhlen

+0

Ich bin weg von meinem Hauptcomputer atm, also kann ich die Fehler nicht hochladen. – MasterArcanist

Antwort

3

aller Erstens, ich glaube nicht, das da, um funktioniert die Mindest und maximaleneine Liste, Sie minimum und maximum verwenden müssen, berechnen; nicht min und max. So eine schnelle Lösung ist:

medVal list = [out | out <- list, out /= minimum list, out /= maximum list]

and when I try to send out the 0th element within the function by adding "!! 0" to the end of the function, it tells me that that's an invalid operation for an integer.

Sie schreiben kann als:

medVal :: Ord a => [a] -> a 
medVal list = [out | out <- list, out /= minimum list, out /= maximum list]!!0

oder eleganter (und schneller):

medVal :: Ord a => [a] -> a 
medVal list = head [out | out <- list, out /= minimum list, out /= maximum list]

Dennoch, wenn Sie sicher wissen, Sie werden erhalten drei Elemente, ich weiß nicht, ob es ein gutes Design ist, eine Liste trotzdem zu verwenden: Sie könnten Definieren Sie eine Funktion mit drei Argumenten oder eine Funktion mit einem Tupel von Elementen.

Schließlich Ihre Funktion wird ein Fehler, wenn zwei oder mehr Elemente gleichwertig (wie medVal [0,0,20]) zum Beispiel sind, da sie alle Elemente herausfiltert und somit head wird ein einzelnes Element nicht gefunden.

+0

Danke! Ich habe aus dem Gedächtnis geschrieben, also nicht alles übertragen. Ich habe die minimalen und maximalen Funktionen verwendet. Ich werde es versuchen, wenn ich zurück bin. – MasterArcanist

+0

@MasterArcanist: Beachten Sie, dass Ihre Funktion - wie im letzten Absatz angegeben - immer noch nicht semantisch einwandfrei ist. –

+0

Ich habe auf Ihren Beitrag vor der Bearbeitung geantwortet. Ich bin nicht vertraut mit dem doppelten Doppelpunkt, Ord a, =>, usw. Dieses Problem entstand, als ich versuchte, eine Lösung für ein Problem bezüglich rechtwinkeliger Dreiecke auf Seite 21 von "Lerne dir ein Haskell zum großen Wohl" zu finden hatte bis zu diesem Punkt gelernt. – MasterArcanist

2

eine elementare Lösung

> let midVal x y z | (z>=x)==(x>=y) = x 
        | (x>=y)==(y>=z) = y 
        | otherwise  = z 

Hinweis: Typo

Fest

Es ist abgeleitet aus der Wahrheitstabelle, sondern einfach, die Zeilen zu lesen, zum Beispiel, wenn entweder x kleiner als z ist und größer als y oder x ist größer als z und y ist größer als x (also x ist in der Mitte) usw.

+0

'midVal 2 5 4' gibt' 2' zurück? Wie auch immer, die obige Logik ist nicht trivial - eine Erklärung würde helfen. – chi

+0

thx. den Tippfehler behoben. – karakfa

+0

Aus irgendeinem Grund funktioniert das bei der Interpretation, aber nicht beim Ausführen des Compilers. Irgendeine Idee warum? In beiden Fällen wurde der Text kopiert/eingefügt, wobei nur der Zeilenabstand geändert wurde. – MasterArcanist

Verwandte Themen