Niedawno zacząłem uczyć się Haskell, ponieważ chciałem poszerzyć swoją wiedzę na temat programowania funkcjonalnego i muszę powiedzieć, że bardzo ją kocham. Zasób, którego obecnie używam, to kurs „Podstawy Haskella, część 1” na temat Pluralsight. Niestety mam pewne trudności ze zrozumieniem jednego konkretnego cytatu prowadzącego na temat następującego kodu i miałem nadzieję, że moglibyście rzucić nieco światła na ten temat.
Kod towarzyszący
helloWorld :: IO ()
helloWorld = putStrLn "Hello World"
main :: IO ()
main = do
helloWorld
helloWorld
helloWorld
Cytat
Jeśli masz tę samą akcję We / Wy wiele razy w bloku do, zostanie ona uruchomiona wiele razy. Tak więc ten program trzykrotnie wypisuje napis „Hello World”. Ten przykład pomaga zilustrować, że putStrLnnie jest to funkcja z efektami ubocznymi. Wywołujemy tę putStrLnfunkcję raz, aby zdefiniować helloWorldzmienną. Gdyby putStrLnmiał efekt uboczny drukowania łańcucha, wydrukowałby tylko raz, a helloWorldzmienna powtórzona w głównym bloku do nie miałaby żadnego efektu.
W większości innych języków programowania taki program wypisuje „Hello World” tylko raz, ponieważ drukowanie nastąpiłoby po putStrLnwywołaniu funkcji. To subtelne rozróżnienie często wprawia w osłupienie początkujących, więc zastanów się nad tym i upewnij się, że rozumiesz, dlaczego ten program drukuje „Hello World” trzy razy i dlaczego wydrukuje go tylko raz, jeśli putStrLnfunkcja wykona drukowanie jako efekt uboczny.
Czego nie rozumiem
Dla mnie wydaje się niemal naturalne, że napis „Hello World” jest drukowany trzy razy. Odbieram helloWorldzmienną (lub funkcję?) Jako rodzaj wywołania zwrotnego, które jest wywoływane później. Nie rozumiem tylko, jak gdyby putStrLnmiał efekt uboczny, to spowodowałoby, że napis byłby wydrukowany tylko raz. Albo dlaczego zostanie wydrukowany tylko raz w innych językach programowania.
Powiedzmy, że w kodzie C # przypuszczam, że wyglądałoby to tak:
C # (skrzypce)
using System;
public class Program
{
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
public static void Main()
{
HelloWorld();
HelloWorld();
HelloWorld();
}
}
Jestem pewien, że przeoczam coś dość prostego lub źle interpretuję jego terminologię. Każda pomoc byłaby bardzo mile widziana.
EDYTOWAĆ:
Dziękuję wszystkim za odpowiedzi! Twoje odpowiedzi pomogły mi lepiej zrozumieć te pojęcia. Nie sądzę, aby kliknięcie zostało w pełni kliknięte, ale wrócę do tematu w przyszłości, dziękuję!
putStrLn nie ma skutków ubocznych; po prostu zwraca akcję IO, tę samą akcję IO dla argumentu "Hello World"bez względu na to, ile razy wywołujesz putStrLn.
helloworldnie byłaby to akcja drukowana Hello world; to jest wartość zwrócony przez putStrLn po to drukowana Hello World(tj ()).
helloWorld = Console.WriteLine("Hello World");. Po prostu zawierać Console.WriteLine("Hello World");w HelloWorldfunkcji mają być wykonane za każdym razem HelloWorldjest wywoływany. Pomyśl teraz o tym, co helloWorld = putStrLn "Hello World"czyni helloWorld. Zostaje przypisany do monady IO, która zawiera (). Gdy go połączysz, >>=dopiero wtedy wykona swoją aktywność (wydrukuje coś) i da ci ()po prawej stronie operatora powiązania.
helloWorldstałej wartości, takiej jak pole lub zmienna w języku C #. Nie stosuje się żadnego parametruhelloWorld.