2013-04-18 26 views
5

tôi muốn mở rộng một trong những module "cốt lõi" hiện có, như Core.Option:Mở rộng mô-đun Core.Option trong F #

module Microsoft.FSharp.Core.Option 

    let filter predicate op = 
     match op with 
     | Some(v) -> if predicate(v) then Some(v) else None 
     | None -> None 

(tôi biết về bind chức năng, nhưng tôi nghĩ filter phương pháp để lựa chọn trong một số trường hợp thuận tiện hơn).

Nhưng unfortunetely tôi không thể sử dụng phương pháp filter mà không explicitely mở Microsoft.FSharp.Core namespace:

// Commenting following line will break the code! 
open Microsoft.FSharp.Core 

let v1 = Some 42 
let v2 = v1 |> Option.filter (fun v -> v > 40) 

printfn "v2 is: %A" v2 

Trong hầu hết các trường hợp chúng tôi không thể sử dụng chức năng từ mô-đun mà không cần mở không gian tên thích hợp. Trình biên dịch F # "mở" một số không gian tên xác định (lõi) tự động (như Microsoft.FSharp.Core), điều này sẽ không đưa vào các phương thức phạm vi từ "mở rộng mô-đun" và chúng ta vẫn nên mở các không gian tên lõi theo cách thủ công.

Câu hỏi của tôi là: Có cách giải quyết nào không?

Hoặc cách tốt nhất để mở rộng các mô-đun "cốt lõi" là tạo các tiện ích mở rộng như vậy trong không gian tên tùy chỉnh và mở không gian tên này theo cách thủ công?

// Lets custom Option module in our custom namespace 
module CustomNamespace.Option 

    let filter predicate op = ... 

// On the client side lets open our custom namespace. 
// After that we can use both Option modules simultaneously! 
open CustomNamespace 

let v1 = Some 42 
let b = 
    v1 |> Option.filter (fun v -> v > 40) // using CustomNamespace.Option 
    |> Option.isSome // using Microsoft.FSharp.Core.Option 
+0

không cần thiết cho các không gian tên tùy chỉnh – Taha

+0

Tôi có rất nhiều ví dụ về điều này - bao gồm hàm chính xác bạn muốn - trong GitHub của tôi: https://github.com/jack-pappas/ExtCore/blob/master /ExtCore/Pervasive.fs –

Trả lời

3

Để mở rộng một F # mô-đun tạo khác có cùng tên:

module Option = 

    let filter predicate op = 
     match op with 
     | Some v -> match predicate v with true -> Some v | false -> None 
     | None -> None 


let v1 = Some 42 
let v2 = v1 |> Option.filter (fun v -> v > 40) 

printfn "v2 is: %A" v2 
+0

Vì vậy, bạn tạo mô-đun tùy chọn trong không gian tên chung. Đó là OK, nhưng tôi không nghĩ rằng đây là giải pháp thích hợp cho mã sản xuất. –

+4

Bạn không phải làm điều đó trong không gian tên chung, miễn là bạn 'mở' vùng chứa có chứa. Đó là cách nó được thực hiện. –

+0

Và bạn có thể đặt một số mô-đun mở rộng trong cùng một không gian tên.Điều này thậm chí còn tốt hơn, vì điều này cho phép kiểm soát các mô-đun mở rộng (và không chỉ tự động bật lên). –

5

Liệu nó giúp đỡ nếu bạn thêm thuộc tính AutoOpen để module?

[<AutoOpen>] 
module Microsoft.FSharp.Core.Option 

    let filter predicate op = 
     match op with 
     | Some(v) -> if predicate(v) then Some(v) else None 
     | None -> None 

EDIT

này hoạt động, nhưng chỉ qua biên giới lắp ráp. Nó không làm việc trong cùng một assembly:

namespace Microsoft.FSharp.Core 
module Option = 
    let filter predicate op = 
     match op with 
     | Some(v) -> if predicate(v) then Some(v) else None 
     | None -> None 

[<assembly:AutoOpen("Microsoft.FSharp.Core")>] 
do() 

Để gọi nó từ lắp ráp khác:

[<EntryPoint>] 
let main args = 
    let f() = Some "" |> Option.filter (fun f -> true) 
    Console.WriteLine("Hello world!") 
    0 
+0

Không, tôi đã thử điều này trước. Điều này sẽ không giúp được gì. Bởi vì thuộc tính AutoOpen áp dụng cho mô-đun chính nó nhưng không áp dụng cho các mô-đun không gian tên. –

+0

@SergeyTeplyakov Câu trả lời cập nhật –

+0

Tuyệt vời, cảm ơn. Tôi đã thử sử dụng thuộc tính AutoOpen trên mô-đun được khai báo. –

5

Đối với mã sản xuất, tôi sẽ làm những gì câu trả lời của Taha gợi ý: tạo mô-đun của riêng bạn và mở/bí danh nó khi cần thiết. Phần lớn cuộc sống của bạn là lập trình viên sẽ được đọc mã. Nó có thể khá bực bội khi đọc mã F # nơi không rõ phương thức đến từ đâu.

Điều đó đang được nói, tôi đã rất ngạc nhiên khi thấy rằng công trình này:

namespace Microsoft.FSharp.Core 

module Option = 

    let filter predicate op = 
     match op with 
     | Some(v) -> if predicate(v) then Some(v) else None 
     | None -> None 

namespace USERCODE 

module Option = Microsoft.FSharp.Core.Option 

module M = 

    let test() = 
     Some 1 
     |> Option.filter (fun x -> x > 0) 
     |> Option.map (fun x -> x + 1) 

Nó không loại bỏ sự cần thiết phải viết một cái gì đó trong đầu của tập tin của bạn, nhưng nó không làm việc xung quanh cần phải mở một không gian tên . Không có liên quan cho Microsoft.FSharp.Core vì nó luôn luôn mở theo mặc định, nhưng hữu ích cho các không gian tên khác.

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