Với phần mở rộng ngôn ngữ, chúng ta có thể tạo ra những tình huống mà f x
phải được đánh giá lặp đi lặp lại:
{-# LANGUAGE GADTs, Rank2Types #-}
module MultiEvG where
data BI where
B :: (Bounded b, Integral b) => b -> BI
foo :: [BI] -> [Integer]
foo xs = let f :: (Integral c, Bounded c) => c -> c
f x = maxBound - x
g :: (forall a. (Integral a, Bounded a) => a) -> BI -> Integer
g m (B y) = toInteger (m + y)
x :: (Integral i) => i
x = 3
in map (g (f x)) xs
Điểm mấu chốt là phải có f x
đa hình thậm chí như là đối số của g
, và chúng ta phải tạo ra một tình huống mà các loại (s) mà tại đó nó là cần thiết không thể được dự đoán (đâm đầu tiên của tôi được sử dụng một Either a b
thay vì BI
, nhưng khi tối ưu hóa, mà tất nhiên dẫn đến chỉ có hai đánh giá của f x
nhiều nhất).
Biểu thức đa hình phải được đánh giá ít nhất một lần cho mỗi loại được sử dụng tại. Đó là một lý do cho sự hạn chế monomorphism. Tuy nhiên, khi phạm vi của các loại nó có thể cần thiết tại bị hạn chế, có thể làm mờ các giá trị ở từng loại, và trong một số trường hợp GHC làm điều đó (cần tối ưu hóa, và tôi mong đợi số lượng các loại liên quan không được quá lớn). Ở đây chúng ta phải đối mặt với những gì cơ bản là một danh sách không đồng nhất, vì vậy trong mỗi yêu cầu g (f x)
, nó có thể cần thiết theo kiểu tùy ý thỏa mãn các ràng buộc, do đó không thể dỡ bỏ tính toán bên ngoài map
(về mặt kỹ thuật, trình biên dịch vẫn có thể xây dựng bộ đệm của các giá trị ở từng loại được sử dụng, do đó, nó sẽ được đánh giá chỉ một lần cho mỗi loại, nhưng GHC không, trong tất cả khả năng nó sẽ không có giá trị rắc rối).
- Biểu thức đơn lẻ chỉ cần đánh giá một lần, chúng có thể được chia sẻ. Cho dù chúng có được thực hiện hay không; bằng sự tinh khiết, nó không thay đổi ngữ nghĩa của chương trình. Nếu biểu thức được gắn kết với một tên, trong thực tế bạn có thể dựa vào nó được chia sẻ, vì nó dễ dàng và rõ ràng là những gì người lập trình muốn. Nếu nó không bị ràng buộc với một cái tên, đó là một câu hỏi tối ưu hóa. Với bộ tạo mã byte hoặc không có sự tối ưu hóa, biểu thức sẽ thường được đánh giá nhiều lần, nhưng với việc tối ưu hóa việc đánh giá lặp đi lặp lại sẽ chỉ ra một lỗi trình biên dịch.
- Biểu thức đa hình phải được đánh giá ít nhất một lần cho mỗi loại mà chúng được sử dụng, nhưng với tối ưu hóa, khi GHC có thể thấy nó có thể được sử dụng nhiều lần cùng loại, nó sẽ (thường) vẫn được chia sẻ cho nhập trong khi tính toán lớn hơn.
Dòng dưới cùng: Luôn biên dịch với tối ưu hóa, giúp trình biên dịch bằng cách ràng buộc các biểu thức bạn muốn chia sẻ với tên và cung cấp chữ ký kiểu đơn khi có thể.
Nguồn
2012-02-25 02:05:12
Bạn có ví dụ về 'f x' đang được đánh giá nhiều lần không? – hammar
@hammar: Tôi đã thêm ví dụ như vậy. –
@Grzegorz Bạn nên đề cập rằng chỉ giữ nếu bạn không tối ưu hóa. Nếu bạn cho phép các loại xếp hạng cao hơn, tôi có thể cung cấp cho bạn ví dụ về việc tối ưu hóa không thể loại bỏ đánh giá lặp lại. Quan tâm? –