GHC có bao giờ giải nén các loại tiền khi chuyển chúng vào các hàm không? Ví dụ, giả sử rằng chúng ta có các loại sau đây:Công ước gọi GHC đối với các đối số hàm kiểu số
data Foo
= Foo1 {-# UNPACK #-} !Int {-# UNPACK #-} !Word
| Foo2 {-# UNPACK #-} !Int
| Foo3 {-# UNPACK #-} !Word
Sau đó, tôi xác định một chức năng đó là nghiêm ngặt trong Foo
đối số của nó:
consumeFoo :: Foo -> Int
consumeFoo x = case x of ...
Khi chạy, khi tôi gọi consumeFoo
, những gì tôi có thể mong đợi xảy ra? Các GHC calling convention là để vượt qua đối số trong sổ đăng ký (hoặc trên ngăn xếp khi có quá nhiều). Tôi có thể thấy hai cách mà đối số đi qua có thể đi:
- Một con trỏ đến một số
Foo
trên heap được chuyển thành một đối số. - Một đại diện ba đối số của
Foo
được sử dụng, một đối số đại diện cho các nhà xây dựng dữ liệu đã được sử dụng và hai người kia đại diện cho thểInt
vàWord
giá trị trong các nhà xây dựng dữ liệu.
Tôi muốn đại diện thứ hai, nhưng tôi không biết nếu nó thực sự là những gì sẽ xảy ra. Tôi biết về việc tải xuống UnpackedSumTypes trong GHC 8.2, nhưng không rõ liệu nó có làm được những gì tôi muốn hay không. Thay vào đó, nếu tôi đã viết hàm như sau:
consumeFooAlt :: (# (# Int#, Word# #) | Int# | Word# #) -> Int
Sau đó, tôi mong rằng đánh giá (2) sẽ là điều xảy ra. Và Unpacking section của trang khoản tiền giải nén chỉ ra rằng tôi có thể làm được điều này cũng như:
data Wrap = Wrap {-# UNPACK #-} !Foo
consumeFooAlt2 :: Wrap -> Int
Và đó cũng nên có các đại diện tôi muốn, tôi nghĩ. Vì vậy, câu hỏi của tôi là, không sử dụng loại trình bao bọc hoặc tổng số chưa được giải nén, làm thế nào tôi có thể đảm bảo rằng một khoản được giải nén vào sổ đăng ký (hoặc lên ngăn xếp) khi tôi chuyển nó làm đối số cho hàm? Nếu nó là có thể, nó là cái gì mà GHC 8.0 có thể đã làm, hoặc là nó một cái gì đó mà sẽ chỉ có sẵn trong GHC 8,2?