2013-04-14 39 views
25

Tôi mới bắt đầu học Haskell, nhưng sự vắng mặt của vòng lặp vô cùng bực bội ngay bây giờ. Tôi đã tìm ra cách viết các vòng lặp cho các hàm. Tuy nhiên, vấn đề của tôi là tôi muốn xuất ra một số kết quả trong khi lặp lại vòng lặp. Dường như tôi phải sử dụng gỡ lỗi để thực hiện tác vụ đơn giản này.vòng lặp Haskell đơn giản

Vì vậy, ngay bây giờ tôi sẽ chỉ đánh giá cao một ví dụ về cách in ra một chuỗi 10 lần trong cấu trúc chính.

Nói cách khác, tôi muốn làm điều này 10 lần:

main = do 
    putStrLn "a string" 

Cảm ơn. Tôi cảm thấy điều này sẽ rất chiếu sáng cho công việc của tôi.

+2

Câu hỏi thực sự cần được trả lời ở đây là khi bạn muốn thực hiện "vòng" bằng ngôn ngữ chức năng, bạn sử dụng đệ quy. Điều pesky duy nhất là nếu bạn nhìn vào nó: các loại không xếp hàng, bởi vì constructor monad (IO, trong trường hợp này). Bởi vì điều đó, bạn cần một cấu trúc đệ quy mà "ghép nối" các monadic ràng buộc tất cả các con đường xuống. Nói cách khác, đây chỉ là đệ quy, với một biến thể nhỏ để xử lý cách "đặc biệt" Haskell đối xử với IO. –

+0

Ngay cả tôi là người mới bắt đầu với Haskell nhưng tôi muốn chia sẻ những gì mà tôi đã đạt được. Có người nói với tôi rằng khi bạn muốn thực hiện các vòng lặp trong Haskell, hãy nghĩ đến việc đệ quy hoặc hiểu danh sách. Không liên quan đến câu hỏi của bạn ở đây, nhưng giả sử bạn muốn thêm tất cả các phần tử vào danh sách. Tất nhiên bạn cần phải lặp qua tất cả các yếu tố. Đệ quy sẽ hoạt động, và do đó sẽ sử dụng một danh sách hiểu. –

Trả lời

36

Bạn có thể định nghĩa một hàm đệ quy mà in "một chuỗi" n lần (n là các tham số của hàm), như thế này:

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

main = printStringNTimes 10 

Một cách tiếp cận hơi tổng quát hơn sẽ được xác định một hàm lặp đi lặp lại bất kỳ hành động IO n lần:

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

main = repeatNTimes 10 (putStrLn "a string") 

chức năng trên đã tồn tại trong Control.Monad dưới cái tên replicateM_.

26

IO của Haskell có chút khó khăn khi bạn mới bắt đầu kể từ khi nó dựa trên đơn nguyên.

Vấn đề của bạn mặc dù có một giải pháp đơn giản:

main = replicateM_ 10 $ putStrLn "a string" 

này được sử dụng combinator replicateM_ từ Control.Monad

Nó có rất nhiều chức năng hữu ích cho việc soạn thảo và thực hiện các hành động monadic.

+13

Để giải thích câu trả lời của bạn vì lợi ích của mình: Haskell có các vòng lặp 'for' và' while', nhưng chúng là các hàm thư viện chứ không phải là các ngôn ngữ được xây dựng sẵn. Ví dụ, tương đương với vòng lặp 'for' là tổ hợp' forM_' từ 'Control.Monad'. Trong trường hợp này, mặc dù 'replicateM_' ngắn gọn hơn. –

+0

Vì vậy, bạn cần phải 'nhập Control.Monad', phải không? – vikingsteve

1

Tôi cũng là người mới bắt đầu của Haskell và tôi có một giải pháp kém thanh lịch hơn nhưng thực dụng hữu ích.

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

Vì vậy, ở đây, chúng tôi đã xác định danh sách, các thành phần trong số đó là các chuỗi mà bạn muốn in ra sau một ký tự dòng mới.

Các vấn đề liên quan