Разделить модули F # на несколько файлов - PullRequest
24 голосов
/ 27 апреля 2009

Можно ли разделить модуль F # по файлам?

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

Ответы [ 5 ]

11 голосов
/ 27 апреля 2009

Видимо нет:

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.

Обновление: ошибка изменилась в F # 4.0, теперь она:

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

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

6 голосов
/ 29 апреля 2009

Расширения типа классные, и, надеюсь, они позволят быть кросс-файлом, , оставаясь при этом внутренними . Если вы делаете расширение типа в том же файле, оно компилируется в один класс, и расширение имеет доступ к закрытым членам и так далее. Если вы делаете это в другом файле, это просто «необязательное» расширение, такое как методы статического расширения 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 #, поэтому они могут иметь список типов или что угодно, вместе с тоннами вспомогательных элементов в модуле.

4 голосов
/ 27 апреля 2009

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

// 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

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

3 голосов
/ 07 ноября 2017

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

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

Вот мои модули:

namespace Xake.FileTasks

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

и другой:

namespace Xake.FileTasks

[<AutoOpen>]
module CpImpl =
    let Cp filemask target =
...
3 голосов
/ 27 апреля 2009

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

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 находятся в разных файлах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...