2013-05-29 15 views
19

Mam pytanie, w jaki sposób GHCi przyjmuje typ liczby całkowitej.Haskell: YesNo type class. Dlaczego Integer?

Czytałem Tak-Nie, klasa typu Ucz się Haskella.

Oto link, jeśli chcesz przeczytać całość.

Krótko mówiąc, ten rozdział pokazuje, że definiując własną klasę, mogę utworzyć funkcję, która działa z wieloma typami.

Książka ta określa klasę TakNie z funkcją

yesno :: a -> Bool 

i uczynić Int jako instancja klasy TakNie

instance YesNo Int where 
    yesno 0 = False 
    yesno _ = True 

Kiedy załadowany to na moim GHCi i wpisane

yesno 0 

zwrócił błąd. Pomyślałem, że to prawdopodobnie dlatego, że GHCi nie może stwierdzić, czy 0 ma być Int lub Integer lub Double lub inny typ w klasie Num. Właściwie kiedy wpisałem yesno (0 :: Int), zadziałało.

Więc po prostu dla zabawy zrobiłem Integer jako przykład YesNo klasy i napisał

instance YesNo Integer where 
    yesno 0 = True 
    yesno _ = False 

(zauważ, że ja przerzucona prawda i fałsz) i znowu, Wpisałem

yesno 0 

(bez dowolna deklaracja typu), następnie GHCi pokazał True.

Ponadto, gdy wpisałem

yesno $ fromIntegral 0 

powrócił True, co oznacza, że ​​GHCi myśli rodzaj fromIntegral 0 jest Integer.

Czy oznacza to, że kiedy po prostu wpisuję liczbę całkowitą w GHCi, zazwyczaj przyjmuje ona wartość: Integer zamiast? Jestem zdezorientowany bo :t 0 zwrotów Num a => a

Odpowiedz

24

Jest to typ defaulting wraz z rozszerzonymi domyślnymi regułami ghci.

Liczba literałów całkowitych jest polimorficzna, mają one typ Num a => a (ponieważ oznaczają one fromInteger literal). Ale kiedy wyrażenie zostanie ocenione - na przykład niezbędne do wydrukowania jego wyniku - wyrażenie musi mieć typ monomorficzny.

Sama

yesno 0 

nakłada dwa ograniczenia Num a i YesNo a na 0, a całe wyrażenie miałoby dwuznaczny rodzaj

yesno 0 :: (Num a, YesNo a) => Bool 

(to jest dwuznaczne, ponieważ typ zmiennej w ograniczenie nie jest osiągalne od typu po prawej stronie =>).

Ogólnie, typy niejednoznaczne są błędami typu, jednak w niektórych przypadkach niejednoznaczność rozwiązuje się, tworząc instancję zmiennej o ograniczonym typie za pomocą typu domyślnego. Przepisy zawarte w specyfikacji języka jest to, że zmienna typu mogą być domyślnie jeśli

W sytuacjach, gdy niejednoznaczne typ jest odkrytych, niejednoznaczne typ zmiennej, v jest defaultable jeżeli:

- `v` appears only in constraints of the form `C v`, where `C` is a class, and 
- at least one of these classes is a numeric class, (that is, `Num` or a subclass of `Num`), and 
- all of these classes are defined in the Prelude or a standard library (Figures 6.2–6.3 show the numeric classes, and Figure 6.1 shows the classes defined in the Prelude.) 

Ograniczenie (Num a, YesNo a) spełnia pierwsze dwa wymagania, ale nie trzecie. Tak więc, według standardu językowego, nie jest to ustawienie domyślne i powinno być błędem typu.

Jednak ghci używa rozszerzonych reguł domyślnych, a także domyślnych zmiennych typu ograniczonych przez klasy nie zdefiniowane w Preludium lub bibliotekach standardowych.

Byłoby następnie wybrać domyślny dla Num przymusu tutaj, chyba wyraźna deklaracja domyślnym jest w zakresie, który byłby Integer, lub, jeśli Integer nie spełnia ograniczeń, Double się starał.

Tak więc, jeśli masz instance YesNo Integer, ghci może z powodzeniem ustawić domyślną zmienną typu a na Integer. Ale jeśli żadna taka instancja nie jest dostępna, ustawienie domyślne nie powiedzie się, ponieważ żaden z domyślnych kandydatów nie ma instancji.

8

Tak, to oznacza, że ​​kiedy wystarczy wpisać cały numer na GHCi, to zwykle przyjmuje jego wartość jest Integer?

Tak. Zasadniczo GHCi najpierw spróbuje Integer, a następnie, jeśli to się nie powiedzie, Double, a następnie ostatecznie (), aby rozwiązać niejednoznaczne ograniczenia typu. Możesz read the details about how this works in the GHC User's Guide.

Należy jednak zauważyć, że w skompilowanych modułach reguły są nieco bardziej rygorystyczne. W szczególności domyślne ustawienie dotyczy tylko klas standardowych, więc Twój przykład nie będzie działał bez adnotacji typu w skompilowanym module, chyba że włączysz rozszerzenie ExtendedDefaultRules, które daje takie samo zachowanie jak GHCi.

1

w pierwszym przypadku próby zapisu:

Prelude> yesno (0 :: Int) 
False 
Powiązane problemy