Frage

Die folgenden Rückgaben sind true (weil 2147483647 eine Primzahl ist).

length [f | f <- [2..(floor(sqrt 2147483647))], 2147483647 `mod` f == 0 ] == 0

Warum funktioniert es nicht, wenn ich versuche, es wie unten zu erweitern?

Prelude> [n | n <- [2..], length [f | f <- [2..(floor(sqrt n))], n `mod` f == 0 ] == 0 ]

<interactive>:1:39:
    Ambiguous type variable `t' in the constraints:
      `RealFrac t' arising from a use of `floor' at <interactive>:1:39-51
      `Integral t' arising from a use of `mod' at <interactive>:1:56-64
      `Floating t' arising from a use of `sqrt' at <interactive>:1:45-50
    Probable fix: add a type signature that fixes these type variable(s)

Ich verstehe jedoch nicht, warum entsteht ein RealFrac aus der Verwendung von Boden? Ich habe RealFracs genommen und Integrale produziert? Außerdem beschwerte es sich nicht mit dem obigen Beispiel, ich füge nur mehr Ganzzahlen wie damals ein.

Prelude> :t floor
floor :: (RealFrac a, Integral b) => a -> b
War es hilfreich?

Lösung

Lassen Sie uns dies leicht entfernen:

Prelude> (\x -> x `mod` (floor . sqrt) x) 2

<interactive>:1:24:
    Ambiguous type variable `b' in the constraints:
      `Floating b' arising from a use of `sqrt' at <interactive>:1:24-27
      `Integral b' arising from a use of `mod' at <interactive>:1:7-30
      `RealFrac b' arising from a use of `floor' at <interactive>:1:16-20
    Probable fix: add a type signature that fixes these type variable(s)

Sie verwenden den Wert von n als Schwimmer, weitergeben sqrt und floor. Sie verwenden dieses Ergebnis dann als INT und geben dieses Ergebnis an weiter an mod. Der Compiler kann einen Typ mit all diesen Instanzen nicht benennen.

Der Grund, warum es in Ihrem ersten Beispiel funktioniert, mit anderen Worten

Prelude> 2 `mod` (floor . sqrt) 2
0

liegt daran, dass Sie zwei verschiedene numerische Literale verwenden. Man kann ein int sein und man kann ein Schwimmer sein. Wenn Sie den gleichen Wert für beide verwenden, müssen Sie anrufen fromIntegral Um den INT in einen Schwimmer umzuwandeln.

Sie können eine andere Fehlermeldung erhalten, indem Sie eine Typ -Signatur hinzufügen, ändern [2..] zu [2..] :: [Integer]:

No instance for (RealFrac Integer)
  arising from a use of `floor' at <interactive>:1:52-64
No instance for (Floating Integer)
  arising from a use of `sqrt' at <interactive>:1:58-63

Dies könnte deutlicher machen, dass Sie den Wert von verwenden n als zwei verschiedene Typen.

Andere Tipps

Wie von Ca McCann unten erwähnt, ist meine Antwort nicht korrekt :-)

Soweit ich sehen kann, liegt es daran, dass die Liste, die Sie erstellen, aus jeder Instanz bestehen kann Floating Seit der Typsignatur von sqrt ist

sqrt :: Floating a => a -> a

Durch Vorkomponieren sqrt mit fromIntegral :: (Integral a, Num b) => a -> b, Sie erhalten das gewünschte Ergebnis:

    Prelude> take 10 $ [n | n <- [2..], length [f | f <- [2..(floor(sqrt (fromIntegral n)))], n `mod` f == 0 ] == 0 ] 
[2,3,5,7,11,13,17,19,23,29]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top