2017-04-18 7 views
0

Ich bekomme einen frustrierenden Fehler, wenn ich versuche, die ersten beiden Ziffern einer Zahl zu extrahieren. Zuerst erarbeite ich die Länge der Ziffer mit log, dann teile ich die Zahl durch die 10^(length of digit - 2), um die ersten zwei Ziffern zu extrahieren. Die len- und divisor-Funktionen funktionieren gut, aber die firstTwo-Funktion schlägt fehl, und ich verstehe das nicht, weil es so einfach zu sein scheint. Ich habe sogar versucht, {-# LANGUAGE FlexibleContexts #-} hinzuzufügen, aber nichts. Bitte helfen. Hier ist der Code:Extrahieren der ersten zwei Ziffern einer Nummer haskell

len n = (+) 1 $ truncate $ logBase 10 n -- length of a digit 

divisor n = 10^(len n - 2) 

firstTwo n = div n divisor 

Der Fehler, den ich bekommen ist:

Nicht typ Variable Argument in der Einschränkung: Integral (r -> a)

(Use FlexibleContexts to permit this) 
When checking that ‘firstTwo’ has the inferred type 
    firstTwo :: forall a r. 
       (Floating r, Integral (r -> a), Num a, RealFrac r) => 
       (r -> a) -> r -> a 
+0

Versuchen Typ Signaturen Hinzufügen eines besseren Fehler zu erhalten. – melpomene

+0

Sie müssen auch überprüfen, dass der Exponent nicht negativ ist.In anderen Worten stellen Sie sicher, dass Ihre Nummer mindestens 2 Ziffern hat. – mathk

Antwort

3

Sie verwenden div auf n und divisor, aber divisor isn‘ t der gleiche typ wie n, es ist eine funktion. Deshalb enden Sie mit Integral (r -> a).

Verwenden firstTwo n = div n (divisor n), aber denken Sie daran, dass logBase funktioniert nur auf Floating wie Double und Float, während div funktioniert nur auf Integral wie Integer und Int. Daher wird es immer noch nicht kompiliert, es sei denn, Sie haben den Typ len geändert.

Fügen Sie Signaturen zu Ihrer Funktion hinzu, um bessere Fehlermeldungen zu erhalten.

+0

Vielen Dank Zeta. Ich verstehe das Problem jetzt. – Amateur

3

Da Sie scheinen, ein Anfänger zu sein mein allererster Rat wäre, Typinformationen so viel wie möglich hinzuzufügen. Zumindest für jede Definition der obersten Ebene (Funktion). Dies hilft Ihnen, dem Compiler und allen anderen, die Ihren Code lesen, Ihre Absicht zu verstehen.

Jetzt für Ihr Problem: Sie versuchen, eine Nummer n durch eine Funktion divisor

div n (divisor n) 

Sollte der Trick zu teilen, auch dort ein kleines Stück fehlt - logBase nicht auf ganze Zahlen arbeiten, während div tut arbeite nur an ganzen Zahlen. Also müssen Sie fromInteger zuerst umwandeln.

Eine Alternative, die mit einer kleinen Anpassung für negative Zahlen arbeiten könnte, könnte take 2 . show sein.

+0

Die Aufnahme 2. Show funktioniert wie ein Charme, danke. – Amateur

1
  1. Konvertieren Sie Ihre Nummer in String.

  2. Überprüfen Sie, ob die Zeichenfolge 2 oder mehr Zeichen enthält.

  3. Wenn die Überprüfung erfolgreich ist, nehmen Sie zuerst 2 Zeichen aus Ihrer Zeichenfolge und konvertieren sie in Int (oder fügen Sie diese Zeichen in Tupel oder machen Sie mit ihnen, was Sie wollen).

  4. Tun Sie etwas mit dem Fall, wenn Ihre Nummer weniger als 2 Ziffern enthält (z. B. Fehler).

    firstTwo :: Integer -> Int 
    firstTwo n 
        | (length . show $ n) >= 2 = read . take 2 . show $ n 
        | otherwise = error "The number contains less than 2 digits" 
    
+0

Danke Arthur für Code. Funktioniert super! – Amateur

Verwandte Themen