2012-10-21 8 views
8

Ich versuche, die Liste mit der kleinsten Summe der Elemente zu finden .:Warum bekomme ich einen Fehler Konnte nicht ableiten (Ord a)?

shortest :: (Num a) => [[a]] -> [a] 
shortest [] = [] 
shortest (x:xs) = if sum x < sum (shortest xs) then x else shortest xs 

Das ist mir die folgenden Fehler gibt:

Could not deduce (Ord a) arising from a use of `<' 
from the context (Eq a) 
    bound by the type signature for shortest :: Eq a => [[a]] -> [a] 
    at code.hs:(8,1)-(9,71) 
Possible fix: 
    add (Ord a) to the context of 
    the type signature for shortest :: Eq a => [[a]] -> [a] 
In the expression: sum x < sum (shortest xs) 
In the expression: 
    if sum x < sum (shortest xs) then x else shortest xs 
In an equation for `shortest': 
    shortest (x : xs) 
     = if sum x < sum (shortest xs) then x else shortest xs 

Warum funktioniert die Funktion typecheck?

+0

"Kürzeste" ist nicht wirklich der richtige Name dafür, oder? - Erwägen Sie die Verwendung von 'minimumBy (vergleichen Sie \ 'on \' sum) 'mit Funktionen höherer Ordnung aus' Data.List' und 'Data.Function'. – leftaroundabout

+1

Um dieses Problem zu verstehen, ist es wichtig zu wissen, dass nicht alle Nummern bestellt werden können. Betrachten wir zum Beispiel komplexe Zahlen wie '1 + 2i'; es gibt keine kanonische Art, sie zu bestellen. – dflemstr

+1

@leftaroundabout schlug bereits eine Lösung mit Bibliotheksfunktionen vor; aber wenn Sie es immer noch von Grund auf als Übung schreiben wollen, müssen Sie neben der Behebung des Typensignaturproblems überlegen, was der Wert von 'kürzestes []' sein soll, oder mit anderen Worten, was die Grundlage der Rekursion sein soll (Hinweis: "Minimum" und "Maximum" sind normalerweise nicht für leere Listen definiert. –

Antwort

15

An diesem Code sind zwei Klassen beteiligt: ​​Num und Ord. Hinweis , dass ein Typ ein Mitglied sein kann Num und nicht Ord und umgekehrt.

Die Art der sumNum a => [a] -> a ist, so dass die Eingabeelemente auf shortest Bedürfnisse Mitglied Num sein. Sie tun auch die folgenden in Ihrem Code:

sum x < sum (shortest xs) 

Dies bedeutet, dass Sie den Operator < auf a s verwenden, aber in Ihrer Art Unterschrift haben Sie nicht erforderlich, dass die a s eine Instanz von Ord sein, die definiert, <:

class Eq a => Ord a where 
    compare :: a -> a -> Ordering 
    (<) :: a -> a -> Bool 
    ... 

Daher müssen Sie diese Anforderung an Ihre Art Signatur hinzuzufügen:

shortest :: (Ord a, Num a) => [[a]] -> [a] 

Oder Sie könnten die Typ-Signatur weglassen.

+4

Eine Möglichkeit, diese Art von Problem zu diagnostizieren und gleichzeitig mehr über Typen und Typklassen zu erfahren, besteht darin, die Typensignatur vorübergehend zu entfernen, das Modul in GHCi zu laden und dann ": t kinestest" einzugeben Compiler zugewiesen. Wenn Sie die Typensignatur weggelassen haben, versuchen Sie es ebenfalls, um festzustellen, ob Ihre Funktion die von Ihnen erwartete Typensignatur aufweist. Ich habe viel gelernt mit dieser Technik. – mhwombat

5

Num enthält nicht Ord, so dass Sie die Ord Einschränkung auf a in der Typ-Signatur fehlt. Es sollte

shortest :: (Num a, Ord a) => [[a]] -> [a] 

Sie sich die Art Signatur entfernen und GHC wird dies für Sie schließen.

Verwandte Themen