2017-02-14 25 views
5

Zdarzyło mi się zobaczyć dziwne zachowanie podczas sprawdzania rozmiaru (minBound, maxBound) i "długość w układzie dziesiętnym" różnych typów integralnych.ghci - domyślne zamieszanie

Korzystanie GHCi:

Prelude> :{ 
Prelude| let mi = minBound 
Prelude|  ma = maxBound 
Prelude|  le = fromIntegral $ length $ show ma 
Prelude| in [mi,ma,le] :: [Int] 
Prelude| :} 
[-9223372036854775808,922372036854775807,2] 
             ^

na ostatnim miejscu chciałbym oczekiwać 19.

Moje pierwsze przypuszczenie że maxBound domyślnie () a tym samym daje 2, ale nie rozumieją, że ponieważ ma powinny być Int przez adnotacją jawne typu (:: [Int]) - i przez więzy przejrzystości wszystkich symboli nazwanych ma powinny być równy.

Po umieszczeniu powyższego wyciągu w pliku i załadowaniu go do GHCi, otrzymuję poprawny wynik.

Dlaczego więc otrzymuję błędny wynik?

+0

Myślę, że pierwsze przypuszczenie jest całkiem blisko, 'ma'” Typ s nie jest ustawiony na "Int" do późniejszego czasu, więc 'le' używa' ma :: Bounded a => a', które domyślnie '' '') w show. Jeśli zrobisz to ponownie za pomocą 'ma = maxBound :: Int', to powinno ci to dać 19. – jkeuhlen

+1

jak to możliwe, że typ nie jest poprawiony? – epsilonhalbe

+0

Każde zachowanie może być mylące, gdy spodziewasz się zachowania przeciwnego. –

Odpowiedz

13

Mylące, nadal jest to ograniczenie monomorfizmu w grze (a raczej jego brak w GHCi). Od GHCi nie posiada ograniczenie monomorfizm włączona, definicje mi i ma nie dostać specjalistyczny do Int jak myślisz, że będzie - zamiast pozostają one ogólnie jako mi, ma :: Bounded a => a i zmienna a dostaje instancji dwukrotnie

  • raz jak () w fromIntegral $ length $ show ma (jak obserwowany, jest to ustawienie domyślne)
  • raz jako Int w [mi,ma,le] :: [Int]

Jeśli chcesz mi i ma faktycznie być typu Int, opisywanie ich jako taki bezpośrednio

Prelude> :{ 
Prelude| let mi, ma :: Int 
Prelude|  mi = minBound 
Prelude|  ma = maxBound 
Prelude|  le = fromIntegral $ length $ show ma 
Prelude| in [mi,ma,le] 
Prelude| :} 
[-9223372036854775808,9223372036854775807,19] 

Albo włączyć ograniczenia monormorphism ręcznie w GHCi

Prelude> :set -XMonomorphismRestriction 
Prelude> :{ 
Prelude| let mi = minBound 
Prelude|  ma = maxBound 
Prelude|  le = fromIntegral $ length $ show ma 
Prelude| in [mi,ma,le] :: [Int] 
Prelude| :} 
[-9223372036854775808,9223372036854775807,19] 
+0

Pomyślałem, że może to być spowodowane "MonomorphismRestriction", ale próbowałem "-XNoMono ..." - który jest już domyślnym ustawieniem w GHCi i ponownie otrzymałem niepoprawny wynik – epsilonhalbe

+3

@epsilonhalbe To jest jedno z niewielu pytań odpowiedział na SO, gdzie ktoś faktycznie chciał mieć "MonomorphismRestriction" (w przeciwieństwie do na odwrót). :) – Alec

+0

Warto chyba zauważyć, że właśnie dlatego ograniczenie monomorfizmu jest generalnie dobrym pomysłem - chyba że podasz bardziej ogólny podpis lub wyraźnie masz funkcję (np. Są argumenty po lewej stronie '='), prawdopodobnie nie będziesz oczekiwać, że twoje wiązanie "let" będzie polimorficzne. W tym przypadku nie oczekujesz, że "mi" lub "ma" będzie polimorficzne z tego powodu. – Alec