Tôi muốn tùy chọn hủy bỏ hành động getChar
. tôi cần những chức năng sau:Làm thế nào để hủy bỏ getChar một cách an toàn?
getChar' :: (Char -> IO()) -> IO (IO())
Trong trường hợp abort <- getChar' callback
, một nhân vật được đọc từ đầu vào tiêu chuẩn, trừ khi abort
được gọi trước khi một nhân vật có sẵn. Nếu một ký tự được đọc, callback
được gọi với ký tự đó.
Tôi có việc thực hiện nguyên mẫu sau:
import Control.Monad
import Control.Concurrent
getChar' :: (Char -> IO()) -> IO (IO())
getChar' callback = do
v <- newEmptyMVar
tid <- forkIO $ do
c <- getChar
b <- tryPutMVar v()
when b $ callback c
return $ do
b <- tryPutMVar v()
when b $ killThread tid
Vấn đề là killThread
có thể hủy bỏ các chủ đề sau khi đọc char nhưng trước khi đưa ()
vào MVAr.
Tôi không biết làm thế nào để giải quyết vấn đề này, có thể nào ở tất cả với gói cơ sở không? Nếu không, bạn có thấy một chức năng tương tự được thực hiện trong các gói khác không?
Cảm ơn! STM và một bộ đệm toàn cầu không thể tránh khỏi ở đây? Bạn nghĩ gì, có thể 'getChar' được định nghĩa trong' IO' quá mà không ảnh hưởng đến ngữ nghĩa của nó? Chỉnh sửa: Tôi đoán có bởi vì 'IO' có thể có trạng thái toàn cục. –
Tôi tự hỏi tại sao 'getChar ':: (Char -> IO()) -> IO (IO())' không có trong 'Prelude' hoặc' System.IO', nó có ngữ nghĩa đơn giản và dường như không thể xác định với các cấu trúc hiện có (ý tôi là không có tham số 'Buffer'). –
1. Có, có hacks để tạo ra các biến toàn cầu trong Haskell. –