2013-04-14 14 views
25

Właśnie zacząłem uczyć się Haskella, ale brak pętli jest teraz nieskończenie frustrujący. Wymyśliłem, jak pisać pętle dla funkcji. Mój problem polega jednak na tym, że chcę wyprowadzić niektóre wyniki podczas iteracji pętli. Wydaje się, że muszę użyć debugowania, aby wykonać to proste zadanie.prosta pętla Haskell

W tej chwili chciałbym po prostu docenić przykład, jak wydrukować ciąg 10 razy w strukturze głównej.

Innymi słowy, chcę zrobić to 10 razy:

main = do 
    putStrLn "a string" 

Dzięki. Czuję, że to będzie bardzo pouczające dla mojego zadania.

+2

Prawdziwym pytaniem, na które należy odpowiedzieć, jest to, że gdy chcesz zrobić "pętle" w języku funkcjonalnym, użyjesz rekursji. Jedyną brzydką rzeczą jest to, że jeśli spojrzysz na to: typy nie ustawiają się w linii, z powodu monadycznego konstruktora (w tym przypadku IO). Z tego powodu potrzebna jest struktura rekurencyjna, która "spiętrza" monadyczne wiązanie do samego końca. Innymi słowy, jest to po prostu rekurencja, z lekką odmianą radzenia sobie z "specjalnym" sposobem, w jaki Haskell traktuje IO. –

+0

Nawet ja jestem początkującym dla Haskella, ale chciałbym podzielić się z wami niewielkim wglądem. Ktoś powiedział mi, że kiedy chcesz robić pętle w Haskell, pomyśl o rekurencji lub spisanych pojęciach. Nie dotyczy to Twojego pytania tutaj, ale załóżmy, że chcesz dodać wszystkie elementy na liście. Oczywiście musisz powtórzyć wszystkie elementy. Rekursja będzie działała, podobnie jak przy użyciu listy zrozumiałej. –

Odpowiedz

36

Można zdefiniować rekurencyjną funkcję, która drukuje „ciąg” n razy (n jest parametrem funkcji), na przykład:

printStringNTimes 0 = return() 
printStringNTimes n = 
do 
    putStrLn "a string" 
    printStringNTimes (n-1) 

main = printStringNTimes 10 

Nieco bardziej ogólne podejście byłoby zdefiniować funkcję, która powtarza żadnych IO działanie n razy:

repeatNTimes 0 _ = return() 
repeatNTimes n action = 
do 
    action 
    repeatNTimes (n-1) action 

main = repeatNTimes 10 (putStrLn "a string") 

powyższe funkcje już w Control.Monad pod nazwą replicateM_.

26

IO Haskella jest nieco trudne, kiedy dopiero zaczynasz, ponieważ bazuje na monadach.

Twój problem chociaż ma proste rozwiązanie:

main = replicateM_ 10 $ putStrLn "a string" 

to przy użyciu syntezatora replicateM_ z Control.Monad

Posiada wiele przydatnych funkcji do komponowania i wykonywania czynności monadycznego.

+13

Aby rozwinąć odpowiedź na swoją korzyść: Haskell ma pętle 'for' i' while', ale są one funkcjami bibliotecznymi, a nie wbudowanymi językami. Na przykład odpowiednikiem pętli 'for' jest kombinator' forM_' z 'Control.Monad'. W tym przypadku jednak 'replicateM_' jest bardziej zwięzły. –

+0

Musisz więc "zaimportować Control.Monad', prawda? – vikingsteve

1

Jestem również początkującym Haskell, i mam rozwiązanie, które jest mniej eleganckie, a jednocześnie jest pragmatycznie przydatne.

main = do 
    putStr result 
    where 
     string = "a string" 
     result = concat [string ++ "\n" | i <- [1,2..10]] 

Więc tutaj mamy zdefiniowane listy, którego elementy są ciągi, które chcesz wydrukować, a następnie znakiem nowego wiersza.