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 "_"?
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 "_"?
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.
Uwaga: Ponieważ '[1 ..]' ma typ polimorficzny, prawdopodobnie ': sp xs' daje' _', nawet po 'head xs'. 'let xs = [1 ..] :: [Integer]' naprawi to. – Zeta
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
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
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
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]
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
spróbuj 'seq c()' po: ': sprint C' daje' C = "a": _' ... przeczytaj także link opublikowany w twoim ostatnim pytaniu – Carsten