2016-02-04 30 views
10
Prelude> let a = 3 
Prelude> :sprint a 
a = _ 
Prelude> let c = "ab" 
Prelude> :sprint c 
c = _ 

Dlaczego zawsze jest drukowany numer _? Nie całkiem rozumiem semantykę polecenia :sprint.Dlaczego: sprint zawsze drukuje "_"?

+0

spróbuj 'seq c()' po: ': sprint C' daje' C = "a": _' ... przeczytaj także link opublikowany w twoim ostatnim pytaniu – Carsten

Odpowiedz

10

Haskell jest językiem leniwy. Nie ocenia wyników, dopóki nie są "potrzebne".

Teraz tylko drukowanie wartość powoduje, że wszystko to jest "potrzebne". Innymi słowy, jeśli wpiszesz wyrażenie w GHCi, spróbuje wydrukować wynik, który spowoduje, że wszystko zostanie ocenione. Zwykle tego właśnie chcesz.

Komenda sprint (która jest funkcją GHCi, nie będącą częścią języka Haskell), pozwala sprawdzić, ile wartości zostało ocenionych w tym momencie.

Na przykład:

Prelude> let xs = [1..] 
Prelude> :sprint xs 
xs = _ 

Tak, właśnie ogłosił xs, a to obecnie unevaluated. Teraz wypiszmy pierwszy element:

Teraz GHCi ocenił głowę listy, ale nic więcej.

Prelude> take 10 xs 
[1,2,3,4,5,6,7,8,9,10] 
Prelude> :sprint xs 
xs = 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : _ 

Teraz pierwsze 10 elementów jest ocenianych, ale więcej pozostaje. (Ponieważ xs jest nieskończona lista, to nie jest zaskakujące.)

Można skonstruować inne wyrażenia i ocenia je nieco w czasie, aby zobaczyć, co się dzieje. To naprawdę część debuggera GHCi, który pozwala ci krok po kroku przejść przez twój kod. Zwłaszcza jeśli twój kod został złapany w nieskończoną pętlę, nie chcesz niczego, co mogłoby blokować GHCi. Ale nadal chcesz zobaczyć, co się dzieje ... stąd sprint, który pozwala zobaczyć, co zostało ocenione do tej pory.

+10

Uwaga: Ponieważ '[1 ..]' ma typ polimorficzny, prawdopodobnie ': sp xs' daje' _', nawet po 'head xs'. 'let xs = [1 ..] :: [Integer]' naprawi to. – Zeta

6

Haskell jest leniwy. Nie ocenia rzeczy, dopóki nie są potrzebne.

Polecenie GHCi sprint (nie będące częścią Haskell, tylko polecenie debugowania interpretera) drukuje wartość wyrażenia bez wymuszania oceny.

Kiedy piszesz

let a = 3 

powiązać nową nazwę a do wyrażenia po prawej stronie, ale Haskell nie oceni jeszcze to coś. Dlatego też, gdy jest to sprint, wypisze _ jako wartość wskazującą, że wyrażenie nie zostało jeszcze ocenione.

Spróbuj tego:

let a = 3 
:sprint a -- a has not been evaluated yet 
print a -- forces evaluation of a 
:sprint a -- now a has been evaluated 
+9

dla 'let a = 3' jest bardziej skomplikowany (powinieneś tego spróbować) - domyślnie' a' będzie 'a :: Num a => a' iw twoim przypadku zawsze będzie ': sprint' do' _' - IMO Przykład 'String' jest lepiej dopasowany do odczucia dla tego – Carsten

+5

jeśli użyjesz' let a = 3', lepiej określ typ 'let a = 3 :: Int', więc nie będziesz się mylić, również zauważ, że to zachowanie zmieniło się w GHC 7.8 w starszych wersjach nie musisz pisać tego typu w tym zestawieniu aby wykonać': sprint' zgodnie z oczekiwaniami'. – epsilonhalbe

3

jestem trochę późno, ale miałem podobny problem:

λ: let xs = [1,2,3] 
xs :: Num t => [t] 
λ: :sprint xs 
xs = _ 
λ: print xs 
λ: :sprint xs 
xs = _ 

Ten problem jest specyficzny dla wartości polimorficznych. Jeśli masz włączoną ghci -XNoMonomorphismRestriction nigdy nie będzie naprawdę ocenić/force xs, będzie to ocenić tylko specjalizacje/force:

λ: :set -XMonomorphismRestriction 
λ: let xs = [1,2,3] 
xs :: [Integer] 
λ: print xs 
λ: :sprint xs 
xs = [1,2,3] 
+2

Należy zauważyć, że dotyczy to tylko "przeciążonych" wartości, takich jak 'xs'; rzeczy, które mają typ ze zmiennymi i mają ograniczenia klasy typów dla tych zmiennych. To głównie przykłady zachowujące się w sposób dosłowny; niestety liczby są oczywistymi rzeczami do zabawy podczas nauki. Jeśli zamiast tego bawisz się przy pomocy booleans ('True',' False', '&&', 'and', itp.), Wszystko w większości zachowuje się tak samo, niezależnie od' NoMonomorphismRestriction' lub czy podajesz jawny podpis typu. – Ben