2009-04-27 30 views
20

Có thể tách mô-đun F # trên các tệp không?Tách F # mô-đun trên nhiều tệp

Theo cuốn sách tôi có nó, nhưng cuốn sách có lẽ là lỗi thời (Foundations of F #)

+1

Câu hỏi này là sai lầm, không rõ ràng và một dup của http://stackoverflow.com/questions/172888/f-định nghĩa-và-sử dụng-một-loại-mô-đun-in-another-file-in-the-cùng-dự án có câu trả lời tốt hơn. IMO đó là ... –

Trả lời

11

Rõ ràng không:

C:\temp\Tim>type 1.fs 2.fs 

1.fs 


#light 
module Module 

let sayHello1 = printfn "Hello, " 

2.fs 


#light 
module Module 

let sayHello2 = printfn "world!" 

C:\temp\Tim>fsc 1.fs 2.fs 
Microsoft F# Compiler, (c) Microsoft Corporation, All Rights Reserved 
F# Version 1.9.6.2, compiling for .NET Framework Version v2.0.50727 

2.fs(2,1): error FS0191: An implementation of the file or module Module has already been given. 

Cập nhật: lỗi đã thay đổi trong F # 4.0, nó bây giờ là:

FS0248 lỗi: hai mô-đun có tên là 'module' xảy ra trong hai phần của hội đồng này

trong đó Module là tên đủ điều kiện của hội đồng của bạn, bao gồm cả phần không gian tên.

+2

Đó là xấu, bởi vì tôi đang làm phân tích cú pháp dữ liệu và có nhiều cấu trúc dữ liệu khác nhau nên tôi đang tạo một tệp F # rất rất dài ... – TimothyP

+0

Thời gian chia nhỏ thành thường xuyên .NET lớp thay vì mô-đun? Hoặc nhiều hơn một mô-đun F #? –

+3

Thật không may F # không hỗ trợ các lớp học một phần, vì vậy bạn thậm chí không thể phân chia một lớp .NET thông thường trên một số tệp nguồn. –

3

đôi khi tôi chia một loại qua nhiều nơi, như thế này:

module Foo 

type Partial = Bar | BarInt of int 

module Bar 

type Foo.Partial with 
    member x.Extend = 5 


let b = Foo.Bar.Extend 

nơi module Foo và Bar là trong các tập tin khác nhau.

4

Giống như Kurt nói, bạn có thể thêm các phương pháp mở rộng các loại, và do đó

// File1.fs 
namespace Foo 

type Mine() = 
    static member f1() =() 

sau đó

// File2.fs 
type Foo.Mine with 
    static member f2() =() 

Foo.Mine. // both f1 and f2 here 

Vì nó là một lớp và không phải là một mô-đun, bạn sẽ mất khả năng làm 'mở Mine '(nhưng đạt được khả năng quá tải); do đó, điều này có thể hoặc không thể là một lựa chọn thay thế có thể chấp nhận được cho bạn tùy thuộc vào chính xác những gì bạn đang làm.

+0

Điều này đúng với Intellisense trong File2.fs, nhưng khi bạn nạp kiểu thông qua sự phản chiếu (ví dụ, typeof (Foo.Mine) .GetMethods(), f2 không hiển thị. Xin cảm ơn mẹo! –

6

Các tiện ích mở rộng kiểu là tuyệt vời và hy vọng chúng sẽ cho phép tệp chéo, trong khi vẫn giữ nguyên nội tại. Nếu bạn thực hiện một phần mở rộng kiểu trong cùng một tệp, nó sẽ biên dịch thành một lớp và phần mở rộng có quyền truy cập vào các thành viên riêng tư, v.v. Nếu bạn làm điều đó trong một tệp khác, nó chỉ là một phần mở rộng "tùy chọn", như phương pháp mở rộng tĩnh C#. (Mặc dù thông số F # khác nhau.)

Tôi sẽ ngạc nhiên nếu điều này không được giải quyết tại một thời điểm nào đó, nếu chỉ dành cho nhà thiết kế hỗ trợ. Nếu phần mở rộng kiểu nội tại có thể ở bất kỳ nơi nào trong hội đồng, điều đó sẽ khá trơn tru.

Một tùy chọn khác, trong đó có thể không phải những gì bạn muốn, là để tạo ra một loại và một mô-đun, gọi module cùng tên, và sau đó thêm lá cờ ModuleSuffix với nó:

type Foo() = 
    static member Bar = 1 

[<CompilationRepresentationAttribute(CompilationRepresentationFlags.ModuleSuffix)>] 
module Foo = 
    let Baz = 2 

printfn "%d %d" Foo.Bar Foo.Baz 

này được sử dụng trong các thư viện F #, vì vậy chúng có thể có một List list hoặc bất cứ thứ gì, cùng với tấn công cụ trợ giúp trong một module.

+2

Điều này là gọn gàng trong F #, nhưng nếu tôi muốn truy cập các kiểu này từ bên ngoài thông qua sự phản chiếu, chúng xuất hiện dưới dạng các loại "Foo" và "FooModule". Dựa trên phản hồi được chấp nhận, không có cách nào để hai kiểu hiển thị cùng loại, lanhung? –

1

Trên một trong các dự án của tôi, mục tiêu là gửi các hoạt động CpRm để phân tách các mô-đun, nhưng không yêu cầu người dùng mở hai không gian tên cho cả hai tác vụ.

open Xake.FileTasks 
... 
do! Cp "*/*.exe" "deploy/*.exe" 
do! Rm "*/*.exe" 

Here're module của tôi:

namespace Xake.FileTasks 

[<AutoOpen>] 
module RmImpl = 
    let Rm filemask target = 
... 

và một trong những khác:

namespace Xake.FileTasks 

[<AutoOpen>] 
module CpImpl = 
    let Cp filemask target = 
... 
Các vấn đề liên quan