2013-02-23 15 views
25

GHCI da mi typ dla 1 ++ 2:Dlaczego ghci daje mi typ "1 ++ 2" zamiast wściekłości?

$ ghci 
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> :t 1 ++ 2 
1 ++ 2 :: Num [a] => [a] 

Ale to jest oczywiście błędne. Jeśli spróbuję i oceniam, zamiast po prostu wpisać, sprawdź, czy coś nie działa poprawnie:

Prelude> 1 ++ 2 

<interactive>:3:1: 
    No instance for (Num [a0]) 
     arising from the literal `1' 
    Possible fix: add an instance declaration for (Num [a0]) 
    In the first argument of `(++)', namely `1' 
    In the expression: 1 ++ 2 
    In an equation for `it': it = 1 ++ 2 

Co daje?

+8

+1 dla tytułu – Mysticial

Odpowiedz

25

Ale to oczywiście nieprawda.

Nie, jest całkowicie poprawny.

Rodzaj (++) jest

(++) :: [a] -> [a] -> [a] 

i rodzaj całkowitych literałów jest

1 :: Num n => n 

Więc typ [a] że argument (++) musiało jest zjednoczone z typem Num n => n że literalna ma, dając

Jeśli masz typ listy z instancją Num, to wyrażenie można również ocenić.

Jednak domyślnie nie ma Num instancja na liście dostępnych typów, więc przy próbie go ocenić, ghci narzeka, że ​​nie stwierdza wystąpienie Num dla [a].

Na przykład:

Prelude> instance Num a => Num [a] where fromInteger n = Data.List.genericReplicate n 1 

<interactive>:2:10: Warning: 
    No explicit method or default declaration for `+' 
    In the instance declaration for `Num [a]' 

<interactive>:2:10: Warning: 
    No explicit method or default declaration for `*' 
    In the instance declaration for `Num [a]' 

<interactive>:2:10: Warning: 
    No explicit method or default declaration for `abs' 
    In the instance declaration for `Num [a]' 

<interactive>:2:10: Warning: 
    No explicit method or default declaration for `signum' 
    In the instance declaration for `Num [a]' 
Prelude> 1 ++ 2 :: [Int] 
[1,1,1] 
+0

Czy to oznacza, że ​​ghci nie jest w pełni typu sprawdzając wyrażenie? Jakiego kroku nie robi ghci przejście od Num [a] do "nie ma Num [a]"? – Dave

+3

Podaje (i sprawdza) typ w zakresie, w jakim można go wywnioskować. To, czego nie robi, polega na sprawdzeniu, czy instancje znajdujące się obecnie w zakresie pozwalają na utworzenie zmiennych typu w sposób, który dałby dobrze wypisane wyrażenie monomorficzne. To dobrze, ponieważ czasami chcesz sprawdzić, jaki typ ma wyrażenie bez zdefiniowania niezbędnych instancji do oceny takiego wyrażenia. Kiedy wyrażenie zostanie ocenione, zmienne typu muszą być tworzone, aby uzyskać typ monomorficzny, a następnie ghci szuka niezbędnych instancji. Jeśli brakuje instancji, jest to zgłaszane. –

+10

Komunikat 'No instance ...' nie oznacza, że ​​wyrażenie jest z natury niepoprawnie napisane, jest (prawdziwe błędy typu otrzymują różne komunikaty); dodając brakujące instancje, możesz (prawie zawsze) uzyskać GHCI, aby je zaakceptować i ocenić. –

16

Bo ktoś mógłby zdefiniować listy należy traktować jako numerami:

instance Num a => Num [a] where 
(+) = zipWith (+) 
(*) = zipWith (*) 
(-) = zipWith (-) 
negate = map negate 
abs = map abs 
signum = map signum 
fromInteger x = [fromInteger x] 

To co wpisałeś będzie działać, ponieważ

1++2 == fromInteger 1++fromInteger 2 == [1]++[2] 

(Nie żeby ta instancja Num miała sens.)

+11

Możesz zdefiniować najczęściej sensowną instancję 'Num' dla wszystkich aplikacji' T' (włączając '[]' i '((->) e)'): 'instancja (Num a) => Num (T a) gdzie fromInteger = czysty. fromInteger; negate = liftA negate; (+) = liftA2 (+); ... ' – melpomene

+2

@melpomene Myślałem, że konkretny przykład będzie tutaj najlepszy. – aleator

Powiązane problemy