2012-01-20 29 views
11

tôi đọc này:ViewPatterns và nhiều cuộc gọi trong Haskell

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

Tôi thích ý tưởng, muốn sử dụng phần mở rộng. Tuy nhiên, tôi muốn đảm bảo một điều: liệu chức năng xem có được đánh giá một lần cho một kết hợp đơn lẻ hay không.

Vì vậy, giả sử chúng ta có:

Bây giờ chúng ta hãy nói rằng tôi gọi f a. view được gọi hai lần hay chỉ một lần cho đối số đã cho a?

EDIT:

tôi đã cố gắng để tìm hiểu xem đây là trường hợp và viết như sau:

{-# LANGUAGE ViewPatterns #-} 

import System.IO.Unsafe 

blah (ble -> Nothing) = 123 
blah (ble -> Just x) = x 

ble x = unsafePerformIO $ do 
    putStrLn $ "Inside ble: " ++ show x 
    return x 

main :: IO() 
main = do 
    putStrLn $ "Main: " ++ show (blah $ Just 234) 

Output sử dụng GHC:

Inside ble: Just 234 
Inside ble: Just 234 
Main: 234 

Output sử dụng GHC (với tối ưu hóa)

Inside ble: Just 234 
Main: 234 

Output sử dụng GHCi:

Main: Inside ble: Just 234 
Inside ble: Just 234 
234 
+0

GHC có một hack đặc biệt để tránh việc tính toán lại các biểu thức giống hệt nhau. – augustss

Trả lời

13

Chỉ một lần:

Hiệu quả: Khi chức năng xem cùng được áp dụng trong nhiều chi nhánh của một định nghĩa hàm hoặc một biểu thức trường hợp (ví dụ, trong size ở trên), GHC cố gắng thu thập các ứng dụng này vào một biểu thức lồng nhau duy nhất, để chức năng xem chỉ được áp dụng một lần. Biên dịch mẫu trong GHC tuân theo thuật toán ma trận được mô tả trong Chương 4 của The Implementation of Functional Programming Languages. Khi các hàng trên cùng của cột đầu tiên của ma trận là tất cả các dạng xem với biểu thức "giống nhau" , các mẫu này được chuyển thành một trường hợp lồng nhau duy nhất. Điều này bao gồm, ví dụ, mô hình xem liền kề mà xếp hàng trong một tuple, như trong

 
f ((view -> A, p1), p2) = e1 
f ((view -> B, p3), p4) = e2 

Khái niệm hiện nay khi hai biểu thức xem mẫu là "những cùng" là rất hạn chế: nó không phải là thậm chí đầy đủ cú pháp bình đẳng. Tuy nhiên, nó bao gồm các biến, chữ, ứng dụng và bộ dữ liệu; ví dụ: hai trường hợp của view ("hi", "there") sẽ là được thu thập. Tuy nhiên, triển khai hiện tại không so sánh với tương đương alpha, do đó, hai trường hợp (x, view x -> y) sẽ không được kết hợp.

- The GHC manual

Đối với đoạn mã của bạn, vấn đề là bạn không biên dịch với tối ưu hóa; với cả hai ghc -Oghc -O2, dòng này chỉ được in một lần.Đó là luôn luôn là điều đầu tiên cần kiểm tra khi bạn có vấn đề hiệu suất liên quan đến khi sử dụng GHC :)

(Bằng cách này, Debug.Trace phép bạn kiểm tra các loại điều mà không cần phải viết tay unsafePerformIO hacks.)

+0

Có thể là GHC đang đưa thêm các đánh giá phụ tùng vì performUnsafeIO? Đừng lo lắng, tôi đã sử dụng nó chỉ để kiểm tra tính năng này. – julkiewicz

+0

Tôi đã thêm một mẫu mã cụ thể. – julkiewicz

+0

@julkiewicz: Tôi đã cập nhật câu trả lời của tôi :) – ehird

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