2013-04-17 13 views
7

Warum hat die folgende Kompilierung:Haskell - Mehrdeutige Variable, warum?

{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE OverlappingInstances #-} 

class IsList a where 
    isList :: a -> Bool 

instance IsList a where 
    isList x = False 

instance IsList [a] where 
    isList x = True 

main = print (isList 'a') >> print (isList ['a']) 

Aber Ändern main zu this:

main = print (isList 42) >> print (isList [42]) 

den folgenden Fehler gibt:

Ambiguous type variable `a0' in the constraints: 
    (Num a0) arising from the literal `42' at prog.hs:13:22-23 
    (IsList a0) arising from a use of `isList' at prog.hs:13:15-20 
Probable fix: add a type signature that fixes these type variable(s) 
In the first argument of `isList', namely `42' 
In the first argument of `print', namely `(isList 42)' 
In the first argument of `(>>)', namely `print (isList 42)' 

isList sicherlich nicht in der Num Klasse es? Und wenn nicht, warum die Zweideutigkeit?

Antwort

10

Das Problem ist nicht mit isList, sondern mit der Konstante 42. Die Konstante 'a' hat eine konkrete Art von Char. Die Konstante 42 hat keinen konkreten Typ.

ghci> :t 42 
42 :: Num a => a 

Der Compiler benötigt einen konkreten Typ. Es wird funktionieren, wenn Sie Haupt zu dem folgenden ändern:

main = print (isList (42 :: Int)) >> print (isList [42 :: Int]) 
+0

Ah, danke, das macht Sinn. Es kann kompilieren, wenn es seinen Typ nicht kennt. Aber warum funktioniert "säumig" hier nicht? Warum nicht Integer? – Clinton

+0

Der Compiler weist nichts darauf hin, dass er das als Int behandeln sollte. Wenn derselbe Bezeichner ... say ... in eine Funktion übergeben wurde, die ein Int benötigt, dann würde der Typ zu Int vereinheitlicht werden. Aber es wird diese Annahme nicht automatisch für Sie treffen. – mightybyte

+9

@Clinton: Die Standardisierung wird nur durchgeführt, wenn sich alle Einschränkungen nur auf Standardklassen beziehen. 'IsList' ist keine Standardklasse. Diese Anforderung kann mit "ExtendedDefaultRules" gelockert werden. – hammar