2013-07-22 8 views
16

Tôi nghĩ rằng đã có một câu hỏi về điều này, nhưng tôi không thể tìm thấy một.GHC: chèn ngày biên soạn

Tôi muốn chương trình của mình in ra ngày được biên dịch. Cách dễ nhất để thiết lập điều đó là gì?

Tôi có thể nghĩ đến một số khả năng, nhưng không cái nào trong số đó là những gì bạn gọi là "dễ dàng". Lý tưởng nhất là tôi muốn có thể chỉ làm ghc --make Foo và có Foo in ra ngày biên soạn mỗi khi tôi chạy nó.

khả năng phi dễ khác nhau mà mùa xuân đến tâm trí:

  • Tìm hiểu Template Haskell. Tìm hiểu cách sử dụng Data.Time để tìm ngày hôm nay. Tìm cách chuyển đổi thành chuỗi. (Bây giờ chương trình của tôi yêu cầu TH để làm việc. Tôi cũng cần thuyết phục nó biên dịch lại mô-đun đó mỗi lần, nếu không tôi sẽ có được ngày biên dịch cho mô-đun đó [không bao giờ thay đổi] thay vì toàn bộ chương trình.)

  • Viết một kịch bản lệnh shell để tạo ra một mô-đun Haskell nhỏ có chứa ngày hệ thống. (Bây giờ tôi phải sử dụng shell script chứ không phải biên dịch chương trình của tôi trực tiếp. Ngoài ra, vỏ kịch bản trên Windows lá nhiều để được mong muốn!)

  • ngồi xuống và viết một số mã Haskell mà tạo ra một module Haskell nhỏ chứa cuộc hẹn. (Di động nhiều hơn ý tưởng trước đó - nhưng vẫn yêu cầu các bước xây dựng bổ sung hoặc ngày được in sẽ không chính xác.)

  • Có thể có một số cách để thực hiện điều này thông qua Cabal - nhưng tôi thực sự muốn đóng gói chương trình nhỏ này để có được một cơ sở ngày?

Có ai có đề xuất đơn giản hơn không?

+1

Bí danh ghc với nội dung nào đó tương đương với '' ghc -DNOW = "\" 'date' \" "' '(không biết cách tìm kiếm vỏ Windows) và trong mô-đun của bạn sử dụng' {- # LANGUAGE CPP # -} 'và' now = NOW' cho chuỗi ngày tháng. Ugly hack, có thể chỉ là xấu xí, đủ để đẩy bạn đến một thay thế sạch hơn mà mất nhiều công việc hơn. –

+0

@DanielFischer Rõ ràng vỏ Windows thiếu khả năng thiết lập một biến từ đầu ra của lệnh. Thay vào đó, bạn phải sử dụng một hack liên quan đến 'SET/P VAR =', mà đọc văn bản từ stdin. Nếu bạn ra lệnh của một đường ống vào một tập tin, sau đó đường ống nó trở lại, bạn có thể đạt được hiệu ứng mà bạn muốn ... nhưng CHÚA GIÊSU !! > _ < – MathematicalOrchid

+0

Ồ, wow. Thậm chí PowerShell không có khả năng đó sao? –

Trả lời

26

Sử dụng mẫu Haskell cho việc này tương đối đơn giản. Bạn chỉ cần:

  1. Run IO hành động trong vòng Template Haskell đơn nguyên:

    runIO :: IO a -> Exp a 
    
  2. Sau đó tạo một chuỗi chữ với:

    stringE :: String -> ExpQ 
    
  3. Đặt một biểu hiện toàn bộ trong vòng một quasiquote.

    $(...) 
    

Chương trình này sẽ in thời điểm biên soạn của nó:

{-# LANGUAGE TemplateHaskell #-} 
import Language.Haskell.TH 
import Data.Time 

main = print $(stringE =<< runIO (show `fmap` Data.Time.getCurrentTime)) 

Bạn có thể đặt đoạn có liên quan vào một module mà nhập khẩu tất cả các module khác để chắc chắn rằng nó được biên dịch lại.

Hoặc lấy thông tin sửa đổi hiện tại từ hệ thống phiên bản của bạn.Xem: TemplateHaskell and IO

+1

Thật là một câu trả lời tuyệt vời đầu tiên! Chào mừng bạn đến với Stack Overflow! – AndrewC

+0

Điều này dường như chỉ là về giải pháp sạch nhất. Chuỗi phiên bản được sử dụng ở nhiều nơi khác nhau, vì vậy tôi sẽ đặt mã này vào một mô-đun riêng biệt. Vấn đề duy nhất tôi thấy trước là nhận được mô-đun phiên bản được biên dịch lại mọi lúc; có lẽ tôi có thể sử dụng TH để "chạm" tập tin nguồn mỗi lần hay gì đó? – MathematicalOrchid

+0

Toán họcOrchid: Đó là lý do tại sao tôi đề xuất rằng mô-đun này nhập khẩu tất cả các mô-đun toplevel khác. Hoặc người ta có thể đặt mã này trong module 'main'. Sau đó, nó luôn luôn được biên dịch lại. Các giải pháp khác có cùng một vấn đề, và cố gắng "chạm" các tập tin nguồn có thể có vẻ giải pháp bẩn hơn đối với một số. –

7

Các preprocessor helpfully định nghĩa __DATE____TIME__ macro (giống như trong C), vì vậy công trình này:

{-# LANGUAGE CPP #-} 
main = putStrLn (__DATE__ ++ " " ++ __TIME__) 

Đây có lẽ là đơn giản hơn so với đề nghị của Template Haskell Michal, nhưng không cho phép bạn chọn định dạng ngày tháng.

+0

tất nhiên, một khi bạn nhận được ngày trong chương trình như là một chữ, bạn có thể mangle mà tuy nhiên bạn thích. – muhmuhten

+0

Tôi đã hy vọng điều này có thể là trường hợp - nhưng tôi không thể tìm thấy bất kỳ đề cập đến nó trong tài liệu. Ngoài ra, có một lý do tại sao viết '" __DATE __ "' không hoạt động, nhưng '__DATE__' của riêng nó không? – MathematicalOrchid

+0

GHC chỉ gọi bộ tiền xử lý C, vì vậy bạn sẽ tìm thấy các macro được xác định trước được ghi lại ở đó. Những cái hữu ích duy nhất là '__DATE__',' __TIME__', '__FILE__' (tên tệp nguồn) và' __LINE__' (số dòng tệp nguồn) - hai số cuối hữu ích để xác định macro lỗi bao gồm vị trí nguồn. Đối với lý do tại sao '" __DATE __ "' không hoạt động, bộ tiền xử lý không mở rộng các macro bên trong một chuỗi ký tự. Bên cạnh đó, '__DATE__' ngày của riêng nó đã mở rộng thành chuỗi ký tự. –