2012-08-07 38 views
21

Trong thư viện đồng thời GHC.Conc, có một hàm gọi là numCapabilities. Loại của nó là numCapabilities :: Int và nó thực sự trả lại một số bạn đã vượt qua bằng cờ dòng lệnh (ví dụ: 5 nếu các tùy chọn là +RTS -N 5).Tại sao numCapabilities là một hàm thuần túy?

Tuy nhiên, getArgs (loại: IO [String]) về cơ bản giống nhau (nó trả về các đối số không có thời gian không được phân bổ) nhưng không phải là hàm thuần túy.

Nếu lý do duy nhất là numCapabilities thường là cần thiết trong mã thuần túy, theo cách nào không phải là các tùy chọn dòng lệnh khác không cần trong mã thuần túy?

Tôi có thiếu gì đó hoặc hoặc là numCapabilities một lỗi thiết kế hoặc tôi có được phép viết con quái vật sau đây không?

myGetArgs = unsafePerformIO getArgs 
+6

Bây giờ tôi tự hỏi ngược lại: Vì giá trị của 'getArgs' không bao giờ thay đổi trong khi chạy chương trình của bạn, tôi không chắc chắn lý do tại sao cần phải/trong' IO'. – sepp2k

+4

Như đã đề cập trong một trong các câu trả lời, nó phụ thuộc vào cách một định nghĩa biểu thức _pure_. Tôi muốn định nghĩa một biểu thức là _pure_ iff nó không phụ thuộc vào bất cứ điều gì ngoài biểu thức chính nó. Theo định nghĩa này, 'numCapabilities' không thuần túy, do đó, có một loại' Int' nên được coi là một lỗ hổng thiết kế. Bạn có thể quan tâm đến bài đăng trên blog của Conal Elliott [Khái niệm về sự thuần khiết trong Haskell] (http://conal.net/blog/posts/notions-of-purity-in-haskell). –

+0

'numCapabilities' không cần trả lại giá trị cho' -N' - nó chỉ gọi 'getNumCapabilities', do đó trả về tuy nhiên nhiều khả năng có lúc đó. Tôi nghĩ rằng đây là một lỗi, thực sự, nhưng thật khó để nói những gì đảm bảo bạn có thể dựa vào trong các mô-đun GHC. –

Trả lời

21

Tôi đã nhìn thấy rất nhiều quan điểm khác nhau về những việc cần làm trong các tình huống như thế này. Một số người nghĩ rằng các giá trị có thể khác nhau giữa biên dịch không được thuần túy và một số nghĩ rằng miễn là giá trị không thay đổi trong thời gian chạy của chương trình (tức là sau khi một số "cấu hình" đã được "thiết lập" main), nó phải tinh khiết.

Gói base dường như đã được giải quyết trên nền tảng trung bình. numCapabilitiessẽ không (theo như tôi biết) thay đổi trong thời gian chạy, nhưng getArgscó thể.

Điều này là do có chức năng withArgs thay đổi số arg bạn nhận được qua getArgs. Vì vậy, câu trả lời đó.

+1

Còn về ['setNumCapabilities'] (http: // www .haskell.org/ghc/docs/latest/html/libraries/base/GHC-Conc.html # v: setNumCapabilities)? –

+9

'numCapabilities' trả về tham số cho' -N # ', trong khi' getNumCapabilities' trả về số lượng khả năng thực sự có. 'setNumCapabilities' thay đổi số thực, được lấy bởi' getNumCapabilities'. Cả hai hàm 'get *' và 'set *' đều nằm trong đơn nguyên 'IO'. – dflemstr

+0

Điều này dẫn đến câu hỏi tại sao có cả 'numCapabilities' và' getNumCapabilities' và không phải cả hai 'args' và' getArgs' – helami

3

Tôi muốn nói đó là một sai lầm, nhưng nó phụ thuộc vào điều mà người ta nghĩ là sự thuần khiết. Xem bài viết Notions of purity in Haskell và thảo luận của nó. Đơn giản chỉ cần đặt, đối số của bài viết là các loại có ý nghĩa, và không có chỗ theo ý nghĩa của Int cho một cái gì đó như numCapabilities, phụ thuộc vào ngữ cảnh thực thi.

15

Oh thân yêu. Nếu bạn nhìn vào định nghĩa của numCapabilities, bạn có thể nhìn thấy nó chỉ là:

numCapabilities :: Int 
numCapabilities = unsafePerformIO $ getNumCapabilities 

và các buổi ghci sau minh họa cho vấn đề:

[[email protected] ~]$ ghci 
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help 
Loading [...] 
ghci> :m +GHC.Conc 
ghci> numCapabilities 
1 
ghci> setNumCapabilities 2 
ghci> numCapabilities 
1 
ghci> :q 
Leaving GHCi. 

[[email protected] ~]$ ghci 
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help 
Loading [...] 
ghci> :m +GHC.Conc 
ghci> setNumCapabilities 2 
ghci> numCapabilities 
2 

Đây là chắc chắn xấu - giá trị của numCapabilities tùy thuộc vào thời điểm được đánh giá liên quan đến bất kỳ cuộc gọi nào có thể tồn tại trong chương trình của bạn theo số setNumCapabilities. Lưu ý rằng trong phiên đầu tiên, numCapabilities vẫn nhất quán, vì IO chỉ được thực hiện trong lần đầu tiên được đánh giá. Tuy nhiên, trong sự hiện diện của nội tuyến (tên không được đánh dấu NOINLINE hoặc bất cứ điều gì), thậm chí điều đó có thể không đúng - bạn có thể về nguyên tắc có hai giá trị khác nhau từ hai lần xuất hiện của numCapabilities (mặc dù trong thực tế tôi đã không thể thực hiện điều này xảy ra).

Vì vậy, câu trả lời là numCapabilitieskhông một chức năng thuần túy, nhưng sai lầm đánh dấu như vậy bởi cửa sau khét tiếng của unsafePerformIO.

0

numCapabilities cho giá trị ban đầu là getNumCapabilities, thời gian hoặc không có đối số cờ RTS -N hiện diện, vì vậy loại phải giống nhau.

Bạn đã thử số này cao hơn số máy tính của bạn chủ đề đồng thời?

$ ghci +RTS -N99 
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help 
Prelude> :m +GHC.Conc 
Prelude GHC.Conc> numCapabilities 
99 
Prelude GHC.Conc> getNumCapabilities 
99 !!! 
Các vấn đề liên quan