2016-09-22 19 views
6

Funkcja Haskell seq wymusza ocenę pierwszego parametru i zwraca trzeci. W związku z tym jest to operator infix. Jeśli chcesz wymusić ocenę wyrażenia, intuicyjnie taka funkcja byłaby operatorem jednoargumentowym. Tak więc, zamiastW jaki sposób używana jest sekwencja Haskella?

seq :: a -> b -> b 

byłoby

seq :: a -> a 

W konsekwencji, jeżeli wartość chcesz to a, dlaczego wrócić b i jak można skonstruować na powrót b. Najwyraźniej nie myślę o Haskellu. :)

+1

Jeśli spojrzysz na [(bardzo źle sformatowaną) definicję 'foldl''' (https://wiki.haskell.org/Seq), zauważysz, że często chcesz po prostu ściśle oszacować niektóre zmienne związane z let-bound w 'a', który podajesz do swojej wartości' b'. –

Odpowiedz

15

Sposób myśleć o a `seq` b nie jest to, że „ocenia a”, ale to, że tworzy zależność między a i b, tak że kiedy idziesz do oceny b ocenić a również.

Oznacza to na przykład, że a `seq` a jest całkowicie zbędny: mówisz Haskellowi, aby ocenił a podczas oceny a. Zgodnie z tą samą logiką, seq a z jednym argumentem nie będzie niczym innym niż samo pisanie a.

Po prostu seq a, że jakoś ocenia a nie będzie działać. Problem polega na tym, że seq a sam jest wyrażeniem, które może nie zostać ocenione - na przykład może znajdować się głęboko w niektórych zagnieżdżonych porachunkach. Tak więc stanie się to istotne tylko wtedy, gdy dojdziesz do oceny całego wyrażenia seq a - w którym momencie i tak sam byś ocenił a.

@ Przykład Rhymoid, w jaki sposób jest używany w ścisłym fałdowaniu (foldl'), jest dobry. Naszym celem jest napisanie takiego fałdu, aby jego pośrednia skumulowana wartość (acc) była w pełni oceniana na każdym etapie, gdy tylko oceniamy wynik końcowy. Odbywa się to poprzez dodanie seq między skumulowanej wartości i rekurencyjnego wywołania:

foldl' f z (x:xs) = 
    let z' = f z x in z' `seq` foldl' f z' xs 

Można wizualizacji tego, jak długi łańcuch seq pomiędzy każdym zastosowaniu f w owczarni, łącząc je wszystkie do wyniku końcowego . W ten sposób podczas oceniania końcowego wyrażenia (tj. Liczby, którą uzyskuje się przez zsumowanie listy), ocenia ona bezpośrednio wartości pośrednie (tj. Sumy częściowe podczas składania przez listę).

+0

Teraz myślę, że zależność utworzona przez 'seq' jest nadmiarowa przynajmniej w przypadku' foldl' jak opisano powyżej, ponieważ zwykłe 'foldl' już narzuca takie ograniczenie zależności na' z'' z powodu używania go. .wydaje się. – George

+2

@George 'foldl (\ x y -> 1) undefined [2]' ocenia na 1, zamiast próbować ocenić 'undefined'. Dla porównania, używając błędów 'foldl'', ponieważ to je ocenia. – chi

+7

@George Jedną z cech, których używasz w innych językach, które nie mają zastosowania do Haskella, jest: aplikacja funkcji oczywiście nie "używa" wszystkich argumentów w aplikacji. W szczególności, tylko dlatego, że aplikacja 'foldl 'f z' xs' ma argument' z'' jako argument, niekoniecznie * (tj. Bez sprawdzenia definicji 'foldl'') oznacza, że' z'' zostanie użyty. Tutaj sprowadza się argument o używanym 'z'':' z'' jest argumentem funkcji, a więc niekoniecznie używanym. –