2013-09-08 34 views
12
import Data.List 
a = foldl' (+) 0 [1..99999999] 
main = putStrLn $ show $ a 

Chương trình này mất một lúc để chạy. Nhưng a không phụ thuộc vào bất cứ điều gì và do đó là không đổi. Nó có thể được tính toán hoàn hảo tại thời gian biên dịch. Tại sao GHC không tối ưu hóa điều này? Có một lá cờ cho nó để làm như vậy, hay tôi nên chỉ thay thế loại tính toán liên tục đó bằng chính các giá trị đó?Tại sao GHC không tối ưu hóa cho các hằng số?

+1

'a' không thực sự khá liên tục vì nó đa hình. GHC loại trừ kiểu như '(Num a, Enum a) => a', mà nội bộ dịch sang một hàm đòi hỏi các đối số từ điển lớp. (Tuy nhiên ngay cả khi bạn làm cho nó 'a :: Int', giá trị sẽ chỉ được tính khi chạy.) – leftaroundabout

+4

Những gì bạn đang nói về được gọi là siêu biên và nó không hoàn toàn dễ dàng như bạn làm cho nó có vẻ. Đó là một chủ đề nghiên cứu và tôi tin rằng một số người đang thử nghiệm điều này với Haskell, nhưng không có nơi nào gần sản xuất đã sẵn sàng. Bạn có thể nhận được nó với một số mẫu Haskell hackery, nhưng nó thường không được khuyến khích. – kqr

Trả lời

6

Điều này giống với cuộc thảo luận được đề cập bởi chuỗi this reddit. Về cơ bản, những gì bạn muốn là nhưng một trường hợp đơn giản mà là không phổ biến trong thực tế. Tối ưu hóa với việc gấp liên tục nhanh chóng biến thành các vấn đề liên quan đến định lý của Gödel và vấn đề Halting.

+4

Tại sao có thể không chỉ là một pragma mà nói "tính toán này tại thời gian biên dịch" để trách nhiệm chứng minh chấm dứt là trên các lập trình viên? –

+0

Vì không ai có thể thực thi cờ đó không được sử dụng mọi lúc. Và điều gì xảy ra nếu ai đó có một mã có thể biến thành hằng số chỉ khi Goldbach là đúng? –

+3

Tôi không hiểu cách áp dụng. Tất cả những gì tôi hỏi là một pragma của trình biên dịch cho biết 'ghc' để cố tính toán giá trị tại thời gian biên dịch. Nếu nó không chấm dứt, thì tôi ổn với điều đó. –

11

Đây không phải là một giải pháp hoàn hảo, nhưng như kqr đã nhận xét bạn có thể dĩ nhiên đạt được mục tiêu của bạn với mẫu Haskell:

{-# LANGUAGE TemplateHaskell #-} 

import Language.Haskell.TH 
import Data.List 

a :: Integer 
a = $(return . LitE . IntegerL $ foldl' (+) 0 [1..99999999]) 

main = print a 

này tạo ra các số nguyên đen 4999999950000000 từ biểu thức lần, trước khi thực sự bắt đầu để biên dịch chương trình.

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