2009-04-27 15 views
20

Можно ли разделить модуль F # на файлы?Разделить модули F # на несколько файлов

Согласно книге у меня есть, но книга, вероятно, устаревшие (Основы F #)

+1

Этот вопрос вводит в заблуждение, неясными и DUP из http://stackoverflow.com/questions/172888/f-define-and-use-a-type-module-in-another-file-in-the-same-project, который имеет лучшие ответы. IMO, который ... –

ответ

11

Видимо нет:

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. 

Update: ошибка изменилась в F # 4.0, это Сейчас:

FS0248 ошибка: два модуля с именем «Модуль» происходит в двух частях этой сборки

где Module - полное имя вашей сборки, включая часть пространства имен.

+2

Это плохо, потому что я занимаюсь анализом данных, и есть много разных структур данных, поэтому я создаю очень очень длинный файл F # ... – TimothyP

+0

Время разбить его на обычный .NET классы вместо модулей? Или более одного модуля F #? –

+3

К сожалению, F # не поддерживает частичные классы, поэтому вы даже не можете разбить обычный класс .NET на несколько исходных файлов. –

3

я иногда разделить типа на несколько мест, например:

module Foo 

type Partial = Bar | BarInt of int 

module Bar 

type Foo.Partial with 
    member x.Extend = 5 


let b = Foo.Bar.Extend 

где модули Foo и Bar находятся в разных файлах.

4

Как Курт говорит, вы можете добавить методы расширения для типов, и, таким образом,

// File1.fs 
namespace Foo 

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

затем

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

Foo.Mine. // both f1 and f2 here 

Поскольку это класс, а не модуль, вы теряете способность делать «открытым Mine '(но получить возможность перегрузки); таким образом, это может быть или не быть приемлемой альтернативой для вас в зависимости от того, что вы делаете.

+0

Это верно для Intellisense в файле File2.fs, но когда вы загружаете тип через отражение (например, typeof (Foo.Mine) .GetMethods(), f2 не отображается. Спасибо за подсказку, хотя! –

6

Расширения типа являются классными, и, надеюсь, они позволят быть перекрестным файлом, , но все еще будучи неотъемлемым. Если вы делаете расширение типа в том же файле, оно компилируется в один класс, а расширение имеет доступ к закрытым членам и так далее. Если вы делаете это в другом файле, это просто «необязательное» расширение, например, методы статического расширения C#. (Хотя спецификации F # говорят по-другому.)

Я был бы удивлен, если это не будет рассмотрено в какой-то момент, если только для поддержки дизайнера. Если внутренние расширения могут быть где угодно в сборке, это было бы неплохо.

Другой вариант, который не может быть то, что вы хотите, чтобы создать тип и модуль, вызовите модуль такое же имя, а затем добавить флаг ModuleSuffix к нему:

type Foo() = 
    static member Bar = 1 

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

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

Это используется в библиотеках F #, поэтому они могут иметь список типов или что-то еще, а также множество вспомогательных материалов в модуле.

+2

Это аккуратно внутри F #, но если я хочу получить доступ к этим типам извне с помощью отражения, они появляются как типы «Foo» и «FooModule». На основании принятого ответа нет способа получить эти два отображения в одном типе, здесь? –

1

В одном из моих проектов целью было файловые операции Cp и Rm для разделения модулей, но не требуют от пользователя открытия двух пространств имен для обеих задач.

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

Here're мои модули:

namespace Xake.FileTasks 

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

, а другой:

namespace Xake.FileTasks 

[<AutoOpen>] 
module CpImpl = 
    let Cp filemask target = 
... 
Смежные вопросы