Tôi đang tạo ứng dụng Haskell tạo ra một số ngẫu nhiên trên một vòng lặp vô hạn (chỉ khi có yêu cầu của khách hàng). Tuy nhiên, tôi chỉ nên sử dụng các hàm thuần túy cho mục đích đó. Có an toàn để bọc randomIO
với unsafeperformIO
mà không có bất kỳ sự ổn định hoặc hiệu suất quyết liệt nào không?Rủi ro khi sử dụng unsafeperformIO trên randomIO
Trả lời
Bất kỳ việc sử dụng nào của unsafePerformIO
phải được chứng minh bằng bằng chứng rằng giá trị kết quả vẫn thuần túy. Sự khắt khe của bằng chứng là tùy thuộc vào bạn và tầm quan trọng của công việc. Ví dụ: việc sử dụng thảm họa unsafePerformIO
và randomIO
này phải an toàn vì bạn có thể chứng minh rằng khi slowTrue
trả lại bất kỳ thứ gì, số này sẽ trả về True
.
import System.Random
import System.IO.Unsafe
import Data.Int
slowTrue = unsafePerformIO $ go
where
go = do
x1 <- randomIO
x2 <- randomIO
if ((x1 :: Int16) == x2) then return True else go
Định nghĩa hấp dẫn sau đây của một toàn cầu, các biến thể ngẫu nhiên là không an toàn:
rand :: Bool -> Int
rand True = unsafePerformIO randomIO
rand False = 0
Vấn đề là cùng một biểu thức bây giờ sẽ mang lại giá trị khác nhau:
main = do
print (rand True)
print (rand True)
in tại đây:
-7203223557365007318
-7726744474749938542
(ít nhất là khi được biên soạn mà không tối ưu hóa - nhưng điều đó chỉ nhấn mạnh sự mong manh của việc sử dụng không phù hợp của unsafePerformIO
).
Đó là một câu hỏi thú vị. Định nghĩa mức cao nhất 'unknown = unsafePerformIO randomIO' thực sự an toàn nếu trình biên dịch sẽ đánh giá nội dung của' unknown' chỉ một lần. Nhưng tôi khá chắc chắn rằng trình biên dịch có quyền inline nó và/hoặc tính toán nhiều lần. – ony
Tôi đã làm điều đó như là ví dụ đầu tiên, nhưng tôi không thể đánh dấu GHC đủ để làm cho điều đó thực sự có thể quan sát được, do đó ví dụ này. –
Bạn nên sử dụng ['random'] (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:random) hoặc [' randomR'] (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:randomR) trong mã thuần túy. –
KHÔNG! Bạn có thể biện minh cho 'unsafeInterleaveIO' nhưng không có gì ngẫu nhiên là thuần khiết! –
@PhilipJF: "không có gì ngẫu nhiên thuần khiết"? Tôi muốn nói những điều như (không phải tại chỗ) quicksort với trục ngẫu nhiên là các thuật toán thuần túy hoàn toàn: ngẫu nhiên không thể được quan sát từ bên ngoài ngoại trừ thông qua các biến thể hiệu suất, mà chỉ có bất kỳ ý nghĩa trong đơn 'IO' anyway. – leftaroundabout