2012-10-16 20 views
8

Tôi đang cố gắng phát triển một máy chủ trò chuyện bằng Haskell.Có thể viết hầu hết mã bằng cách sử dụng IO monads

Có rất nhiều công cụ hữu ích như TChan, TSkiplist, forkIO ... vv, nhưng nó quay ra rằng hầu hết các mã của tôi được viết bên trong monads IO và unsafePerformIO, mà âm thanh rất kém hiệu quả.

Có ổn không khi thực hiện việc này hoặc không có công cụ phù hợp với mục đích này không?

+1

Hãy xem [Hulk] (http://chrisdone.com/posts/2011-01-30-hulk-haskell-irc-server.html) - bắt đầu viết một máy chủ IRC trong Haskell. – ErikR

Trả lời

19

Theo nguyên tắc chung, hãy thử trước tiên viết mã như các hàm thuần túy mà không phải lo lắng dữ liệu đến từ đâu - giả sử nó ở đó.

Tiếp theo bọc chức năng thuần túy đó vào IO để nạp dữ liệu chức năng thuần túy của bạn và đặt kết quả ở đâu đó. OK là có điều này đang diễn ra trong ứng dụng trò chuyện! Các đơn nguyên IO là không hiệu quả ở tất cả, nó chỉ là chúng tôi muốn giữ càng nhiều mã như chúng ta có thể ra khỏi nó vì đó là thiết kế tốt - giữ dữ liệu crunching ngoài IO. Một ứng dụng trò chuyện không thực hiện nhiều phép tính với dữ liệu mà nó nhận được, vì vậy có thể tải được mã IO.

Tôi nghĩ rằng nó chắc chắn tốt hơn để dính vào đơn nguyên IO hơn sử dụng unsafePerformIO, bởi vì unsafePerformIO là loại trình bày kết quả của nó như là dữ liệu thuần túy. Tôi có thể là bị cám dỗ để sử dụng nó để lấy các hằng số từ tệp cấu hình, nhưng tôi chưa bao giờ thực sự làm như vậy và không có vấn đề gì nếu bạn đang sử dụng đơn lẻ IO. Có một lý do nó được gọi là không an toàn! Petr Pudlák có lời khuyên tốt trong phần bình luận bên dưới.

Tôi đã nghe các bài hát của Haskell được mô tả là best imperative programming language trong thế giới . Tôi có thể tách lông trên mô tả đó, nhưng tôi đồng ý với tình cảm, và có, gắn bó với Haskell. Haskell giỏi về lập trình bạn đang sử dụng.

+4

Câu trả lời hay. Chỉ cần tôi ủng hộ mạnh mẽ hơn nhiều khi sử dụng 'không an toàn * '. Sử dụng 'unsafe *' sẽ làm cho bạn mất những gì Haskell thực thi bạn - để tách các tính toán tinh khiết và không tinh khiết. Và kết hợp với đánh giá lười biếng, 'không an toàn *' sẽ làm cho cuộc sống của bạn khốn khổ. –

+1

Điểm tốt. Tôi đã tăng cường những lời khuyên chống lại không an toàn, nhưng tôi đã để lại điểm về lười biếng + không an toàn cho bình luận tốt của bạn. – AndrewC

+1

Cảm ơn câu trả lời tuyệt vời! – user1748906

12

Bất cứ khi nào bạn nhận thấy rằng bạn có chức năng dài nằm bên trong đơn nguyên IO, nó trả tiền để tạm dừng và xem xét các tính toán diễn ra. Theo kinh nghiệm của tôi, đó là (hầu như) luôn trường hợp một số nội dung không liên quan đến IO đang diễn ra mà không cần truy cập vào đầu ra đầu vào và có thể được đóng gói trong các hàm tinh khiết.

Điều này có lợi thế lớn là nó buộc bạn phải tìm các thuật toán trừu tượng thích hợp và các thuật toán riêng biệt (thuần túy) từ xử lý đầu vào/đầu ra. Hơn nữa, nó dễ dàng hơn nhiều để xác minh và thử nghiệm các hàm thuần túy. Tất nhiên, bạn sẽ vẫn gọi những chức năng thuần túy này từ một số chức năng IO a (ví dụ: main) nhưng điều đó hoàn toàn ổn.

5

nhất của mã của tôi được viết bên trong monads IO

Đó là tốt.

và unsafePerformIO

Đó là xấu! Tránh sử dụng unsafePerformIO như bệnh dịch hạch; nó chỉ nên được sử dụng bởi Haskellers kỳ cựu trong những trường hợp rất cụ thể.

Bạn có muốn làm điều này hay không phải là công cụ thích hợp cho mục đích này không?

OK để viết mã trong đơn IO, nhưng không OK để sử dụng unsafePerformIO. Thay vào đó, hãy tìm hiểu cách soạn các hành động IO bằng cách sử dụng giao diện Monad (ký hiệu do). Tìm hiểu chữ ký loại chức năng nào cần bao gồm loại IO.

+2

Tránh sử dụng unsafePerformIO! làm thế nào để bắt đầu giao dịch stm trong mono io? – user1748906

+2

@ user1748906 Sử dụng 'nguyên tử'. –

+3

@ user1748906 nếu bạn hoogle chữ ký loại [STM a -> IO a] (http://www.haskell.org/hoogle/?hoogle=STM+a+-%3E+IO+a), lần truy cập đầu tiên là ' nguyên tử, như ngọn lửa của Ptharien gợi ý. –

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