2015-03-23 22 views
5

napisałem następujący fragment kodu:Dziwne zachowanie w GHCi

it :: Int -> Int 
it n 
    | n < 1  = error "Invalid entry." 
    | n == 1 = 0 
    | otherwise = 1 + it (n `quot` 2) 

Kiedy załadować go do GHCi, coś dziwnego się dzieje. Po raz pierwszy wywołuję funkcję it, działa dobrze i zwraca oczekiwane wyniki. Jednak następnym razem, pojawia się następujący katastrofę:

λ: :t it 
it :: Int -> Int 
λ: it 2 
1 
λ: it 2 

<interactive>:4:1: 
    Couldn't match expected type `a0 -> t0' with actual type `Int' 
    The function `it' is applied to one argument, 
    but its type `Int' has none 
    In the expression: it 2 
    In an equation for `it': it = it 2 
λ: :t it 
it :: Int 
λ: it 
1 

Wydaje się, że typ it jest w jakiś sposób zmodyfikowane po pierwszej rozmowy. Robi się jeszcze dziwniejsze gdy it nazywa się wielokrotnie z main, czyli wszystkie połączenia powrócić oczekiwanych rezultatów, ale w końcu () jest przypisany jako typ it:

main :: IO() 
main = do 
    let r1 = it 1 
     r2 = it 2 
     r3 = it 3 
    print r1 
    print r2 
    print r3 

λ: main 
0 
1 
1 
λ: :t it 
it ::() 

wierzę, że jest to błąd związany z Identyfikator it i elementy wewnętrzne GHCi, ponieważ zmiana nazwy funkcji na coś innego (jako it') całkowicie rozwiązuje problem. Poza tym ciało funkcji wydaje się nie mieć wpływu; Robienie let it = (+) 2 i ocenianie go wiele razy jest również problematyczne.

Każdy wgląd byłby doceniony. Wyjście ghci --version to "wersja 7.6.3".

Odpowiedz

11

Pech nazywania: it to nazwa GHCi automatycznie wiąże się z wynikiem z poprzedniej oceny, dzięki czemu można wygodnie odnieść się do niego ponownie. Więc twoje pierwsze użycie natychmiast ponownie je wiąże, śledząc twoją definicję.

Jeśli w module zdefiniowano it, powinieneś być w stanie odnieść się do niego niezawodnie z GHCi z prefiksem modułu, np. Main.it.

+0

Dzięki za odpowiedź! Cieszę się, że to tylko kolejny przypadek dylematu "bug vs feature". :-) Z pewnością widzę użyteczność "tego", ale zastanawiam się, czy istnieje lepszy sposób, aby ta funkcja mogła zostać zaimplementowana w GHCi, aby uniknąć takiego zamieszania ... Może za pomocą specjalnego słowa kluczowego, zamiast prawidłowej funkcji Haskella identyfikator? Lub przynajmniej ostrzeżenie użytkownika podczas ładowania funkcji o nazwach zastrzeżonych GHCi ... Wreszcie, czy są jakieś inne specjalne nazwy w GHCi, o których powinienem wiedzieć? –

+1

@alexandrelucchesi Przypominam sobie z drogi powrotnej, że Hugs używał zamiast tego '$$', chociaż można go pomylić z operatorem. Myślę, że GHCi używa zwykłego identyfikatora, ponieważ funkcja jest zaimplementowana jako normalny kod, patrz [podręcznik] (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/interactive-evaluation.html#idp7106400). Nie znam żadnych innych specjalnych nazw, ': show binding' nie wyświetla więcej. –