2010-04-24 49 views
5

Tôi gặp vấn đề với IO không thực hiện theo thứ tự, ngay cả bên trong một cấu trúc làm.Tại sao IO không được thực thi theo thứ tự?

Trong đoạn mã sau, tôi chỉ theo dõi thẻ nào còn lại, trong đó thẻ là một bộ ký tự (một cho phù hợp và một cho giá trị), sau đó người dùng liên tục được hỏi về thẻ nào đã được phát. Tôi muốn putStr được thực hiện giữa mỗi đầu vào và không phải ở cuối cùng như hiện tại.

module Main where 
main = doLoop cards 
doLoop xs = do putStr $ show xs 
       s <- getChar 
       n <- getChar 
       doLoop $ remove (s,n) xs 
suits = "SCDH" 
vals = "A23456789JQK" 
cards = [(s,n) | s <- suits, n <- vals] 
type Card = (Char,Char) 
remove :: Card -> [Card] -> [Card] 
remove card xs = filter (/= card) xs 

Trả lời

8

Câu trả lời của absz là chính xác, IO đệm của Haskell là những gì gây ra rắc rối cho bạn. Dưới đây là một cách để viết lại doLoop của bạn để có hiệu quả bạn đang tìm kiếm:

doLoop xs = do putStrLn $ show xs 
       input <- getLine 
       let s:n:_ = input 
       doLoop $ remove (s,n) xs 

Hai thay đổi này: sử dụng putStrLn để thêm một dòng mới và tuôn đầu ra (mà có lẽ những gì bạn muốn), và sử dụng getLine để lấy đầu vào một dòng tại một thời điểm (một lần nữa, có lẽ là những gì bạn muốn).

+0

Mã lỗi! Bạn giới thiệu một sự thất bại về mô hình potentiel ở đây. –

+0

True, trường hợp là xa đầy đủ, nhưng như là một bằng chứng về khái niệm (liên quan đến các hoạt động IO) nó hiện công việc. – perimosocordiae

14

Nếu vấn đề là những gì tôi nghĩ, vấn đề của bạn là IO của Haskell được đệm: this question giải thích những gì đang xảy ra. Khi bạn chạy một chương trình Haskell đã biên dịch, GHC lưu trữ kết quả đầu ra trong bộ đệm và chỉ định kỳ đưa nó vào màn hình; nếu không (a) bộ đệm quá đầy, (b) nếu một dòng mới được in, hoặc (c) nếu bạn gọi hFlush stdout.

Sự cố khác mà bạn có thể thấy là getChar có thể không kích hoạt cho đến khi một dòng mới được đọc, nhưng sau đó dòng mới nằm trong luồng đầu vào của bạn; bạn có lẽ có thể giải quyết điều này với một số getChar để nuốt dòng mới, nhưng có lẽ nên có cách tốt hơn.

+0

Yep, cuộc gọi tốt. Chỉ cần thử nó; hoạt động tốt trong GHCi, không in được gì cho đến khi kết thúc khi được biên dịch, giống như câu hỏi bạn đã liên kết. –

6

Đệm, dưới dạng putStr, là vấn đề của bạn, như những người khác đã chỉ ra.

Ngoài ra, một điểm phong cách: putStrLn $ show xs cũng giống như print xs

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