Ich war so müde, dass ich schrieb den folgenden Code (zeige geändert, nur die Verwirrung):Haskell: Warum gibt es keinen Typunterschied (und warum kompiliert er)?
fac s = take 10 [s, s `mod` 1 ..]
maxFactor x = if (s == [])
then x
else head <-- this should be 'head x' instead of just 'head'
where s = fac x
jedoch diese Last in GHCI (und kompiliert) einwandfrei. Als ich maxFactor 1
ausgeführt, klagt es (natürlich):
<interactive>:0:1:
No instance for (Integral ([a0] -> a0))
arising from a use of `maxFactor'
Possible fix:
add an instance declaration for (Integral ([a0] -> a0))
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
<interactive>:0:11:
No instance for (Num ([a0] -> a0))
arising from the literal `1'
Possible fix: add an instance declaration for (Num ([a0] -> a0))
In the first argument of `maxFactor', namely `1'
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
Aber ich dieses Verhalten nicht verstehen:
fac
's Typ:
fac :: Integral a => a -> [a]
während maxFactor
' s Typ ist:
maxFactor :: Integral ([a] -> a) => ([a] -> a) -> [a] -> a
Bedeutet dies nicht th e folgendes:
- der erste Eingang mit
fac
Integral
von typeclass sein muß (z.B.fac 10
); - da in der Definition von
maxFactor
gibt esfac x
, x muss auch seine typeclassIntegral
somitmaxFactor
‚s Art mit so etwas wiemaxFactor :: (Integral a) => a ->
beginnen würde ... dann noch etwas anderes? Wenn dies jedoch der Fall ist, warum kompiliert dieser Code seit der Rückkehr vonmaxFactor
x
oderhead
, die, wenn diese Argumentation folgt, nicht den gleichen Typ?
Was fehlt mir hier?
Vielen Dank für alle Eingaben im Voraus!
Diese Art von Problem kann in einer viel einfacheren Art und Weise auftreten. Ich vermute (aber ich bin kein Experte), dass es passieren kann, wenn der Typ-Checker einen Ausdruck nicht ausreichend reduzieren kann. Zum Beispiel foo x = 1 + x; bar = foo head - wird fehlschlagen, aber foo x = 1 + x; bar x = foo head - wird kompiliert. – Sarah
@Sarah: Das von Ihnen angegebene Beispiel wird wegen der Monomorphieeinschränkung nicht überprüft. Wenn du Pragma hinzufügst, gibt es einen Tippfehler (es gibt jedoch ein kleines Problem: GHCi leitet den Typ 'Num ([a] → a) ⇒ [a] → a' ein und du kannst mit diesem Typ nicht' bar' deklarieren, du brauchst FlexibleContexts dafür). – Vitus
Für was es wert ist, wenn Sie mit "-Wall" kompilieren (oder fügen Sie das zu Ihren Standard-Ghci-Optionen, so dass Ghci "kompiliert" mit "-Wall") erhalten Sie eine Warnung, weil Sie keinen Typ gesetzt haben Signatur auf 'maxFactor'. Dann schreiben Sie vermutlich 'maxFactor :: Integral a => a -> a 'und es wird nicht kompiliert. – MatrixFrog