2012-04-04 15 views
7

Tôi cố gắng để thực hiện một chức năng hẹn giờ generic trong OCaml sẽ diễn như là đầu vào một chức năng của arity tùy ý và kiểu trả về 'r và trả về một chức năng với:generic chức năng hẹn giờ theo đơn đặt hàng cao trong OCaml

  • các arity cùng và các loại đầu vào thông số , và
  • trở lại loại float * 'r nơi phao sẽ là một thước đo của thời gian dành cho chức năng (ví dụ như báo cáo của Sys.time())

Vấn đề là tôi không thể thực hiện nó theo cách mà nó có thể xử lý các chức năng của bất kỳ điều gì. Ví dụ. đoạn mã sau:

 
let timer f =    
    let timerf x y =         
     let t0 = Sys.time()           
     in let result = f x y             
     in let diff = Sys.time() -. t0          
     in diff, result          
    in timerf  

chỉ hoạt động với các chức năng của nguyên tử đầu vào 2. Tôi không hiểu rõ cách xử lý các chức năng của bất kỳ nguyên tử nào. Tôi đã hy vọng các ứng dụng chức năng một phần bằng cách nào đó sẽ giải quyết một cách kỳ diệu câu hỏi hóc búa nhưng tôi không thể làm cho nó hoạt động được.

Trả lời

9

Tôi hiểu ý định của bạn về việc thực hiện chức năng hẹn giờ với tinh thần tùy ý. Nhưng bạn không thể làm điều đó một cách dễ dàng trong OCaml.

Hơn nữa, chức năng hẹn giờ chỉ với một param là đủ để sử dụng trong thực tế:

let timer f x = 
    let t0 = Sys.time()           
    in let result = f x            
    in let diff = Sys.time() -. t0          
    in diff, result 

Kể từ bất kỳ chức năng g với bất kỳ arity thể được truyền cho timer dễ dàng bằng cách:

let diff, result = timer (fun() -> g x1 x2 x3 ... xN)() 

hoặc tốt hơn bằng cách sử dụng một phần ứng dụng (như được đề xuất bởi @Andreas):

let diff, result = timer (g x1 x2 x3 ... xN-1) xN 
+0

Nếu bạn biết rằng hàm không làm bất cứ điều gì thú vị khi áp dụng một phần (giống như hầu hết các hàm) thì bạn thậm chí không cần sự trừu tượng. Nó đủ để gọi 'timer (g x1 x2 ... xN-1) xN'. –

+0

@AndreasRossberg: Cảm ơn, tôi đã kết hợp ý kiến ​​của bạn vào câu trả lời của tôi. – pad

7

Nhận xét về giải pháp của pad quá dài để phù hợp với nhận xét.

Trong thực tế, tôi nhận thấy đó là thiết kế tốt hơn để thực thi f : unit -> 'a bằng cách chuyển () thay vì đối số bị trì hoãn.

let timer f = 
    let t0 = Sys.time() in 
    let result = f() in 
    let t1 = Sys.time() in 
    t1 -. t0, result 

Lý do tại sao mà tôi có xu hướng sử dụng mẫu sau khá thường xuyên:

let fun_to_test = match some_configuration with ... in 
timer fun_to_test 

thiết kế pad, mà là hấp dẫn hơn lúc đầu vì tổng quát hơn, khuyến khích bạn thay vì viết:

let fun_to_test, arg = match some_configuration with .... in 
timer fun_to_test arg 

Vấn đề với lựa chọn này là ban đầu, và sau khi thêm một vài tùy chọn, bạn gặp trường hợp đối số với các hàm khác nhau để kiểm tra không phải là của ame loại. Và bạn có lỗi kiểu. Ví dụ về sai mã:

let fun_to_test, arg = 
    if Random.bool() 
    then (foo, 3) 
    else (bar, 3.2) 
in timer fun_to_test arg 

By buộc đóng cửa với các thông số trước khi trôi qua, tôi nhận được "một kiểu hiện sinh" miễn phí tại đây: kiểu của đối số chức năng cuối cùng không xuất hiện trong các loại timer ứng dụng. Tôi thấy điều này tốt hơn trong thực tế.

Tất nhiên, bạn cũng có thể trì hoãn cuộc gọi đầy đủ và sử dụng () làm đối số trong thiết kế của bàn phím. Nhưng tôi thích một sự lựa chọn buộc tôi phải làm điều này, bởi vì nếu không tôi quá cám dỗ không làm điều đó, và tôi trả nó sau.

+0

giây kinh nghiệm của tôi này – ygrek

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