Natrafiłem na następującą definicję, próbując nauczyć się Haskell, używając prawdziwego projektu do jej prowadzenia. Nie rozumiem, co oznacza wykrzyknik przed każdym argumentem, a moje książki chyba o tym nie wspominały.
data MidiMessage = MidiMessage !Int !MidiMessage
haskell
syntax
lazy-evaluation
David
źródło
źródło
Odpowiedzi:
To deklaracja ścisłości. Zasadniczo oznacza to, że należy go ocenić do tak zwanej „postaci normalnej słabej głowy” podczas tworzenia wartości struktury danych. Spójrzmy na przykład, abyśmy mogli zobaczyć, co to znaczy:
Powyższa funkcja
f
po ocenie zwróci „thunk”: kod, który należy wykonać, aby obliczyć jego wartość. W tym momencie Foo jeszcze nie istnieje, tylko kod.Ale w pewnym momencie ktoś może spróbować zajrzeć do środka, prawdopodobnie poprzez dopasowanie wzoru:
Spowoduje to wykonanie kodu wystarczającego do zrobienia tego, czego potrzebuje, i nic więcej. Stworzy to Foo z czterema parametrami (ponieważ nie możesz zajrzeć do niego bez jego istnienia). Po pierwsze, odkąd go testujemy, musimy ocenić aż do miejsca
4
, w którym zdajemy sobie sprawę, że nie pasuje.Drugiego nie trzeba oceniać, ponieważ go nie testujemy. Tak więc, zamiast
6
być przechowywane w tej lokalizacji pamięci, będziemy po prostu zapisać kod do ewentualnej późniejszej oceny(3+3)
. To zmieni się w 6 tylko wtedy, gdy ktoś na to spojrzy.Trzeci parametr ma jednak
!
przed sobą, więc jest ściśle oceniany:(4+4)
jest wykonywany i8
jest przechowywany w tym miejscu pamięci.Czwarty parametr jest również ściśle oceniany. Ale tutaj jest nieco trudniej: oceniamy nie w pełni, ale tylko do słabej normalnej postaci głowy. Oznacza to, że ustalamy, czy to,
Nothing
czyJust
coś, i przechowujemy to, ale nie idziemy dalej. Oznacza to, że przechowujemy nie,Just 10
ale faktycznieJust (5+5)
, pozostawiając thunk w środku nieocenionym. To ważne, aby wiedzieć, choć uważam, że wszystkie implikacje tego wykraczają poza zakres tego pytania.Możesz opisać argumenty funkcji w ten sam sposób, jeśli włączysz
BangPatterns
rozszerzenie języka:f (1+1) (2+2)
zwróci thunk(1+1)*4
.źródło
seq
.Prostym sposobem na dostrzeżenie różnicy między ścisłymi i niesurymi argumentami konstruktora jest to, jak zachowują się, gdy są niezdefiniowane. Dany
Ponieważ nieprecyzyjny argument nie jest oceniany przez
second
, przekazanieundefined
nie powoduje problemu:Ale ścisłym argumentem nie może być
undefined
, nawet jeśli nie użyjemy wartości:źródło
!
ma symbol, zamiast zagłębiać się w wewnętrzne szczegóły implementacji.Uważam, że jest to adnotacja o ścisłości.
Haskell jest czystym i leniwym językiem funkcjonalnym, ale czasem lenistwo może być zbyt duże lub zbyteczne. Aby sobie z tym poradzić, możesz poprosić kompilatora o pełną ocenę argumentów funkcji zamiast analizowania.
Na tej stronie znajduje się więcej informacji: Wydajność / Surowość .
źródło
map Just [1,2,3]
aby uzyskać [Tylko 1, Tylko 2, Tylko 3]) i tak dalej. Uważam, że warto pomyśleć o możliwości dopasowania do nich wzoru, a także o zupełnie niezwiązanym obiekcie.