2013-04-25 30 views
5

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

+5

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. –

+1

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! –

+6

@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

Trả lời

12

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 unsafePerformIOrandomIO 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).

+0

Đó 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

+2

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. –

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