Разделение между модулями и пространствами имен в F #

У меня есть проблема в понимании точной разницы между модулями и пространствами имен в F # и при использовании того или другого. Ну, они оба рассматриваются для того, чтобы инкапсулировать код и определить иерархию, чтобы наши проекты были хорошо организованы.

Модули имеют множество функций: они могут содержать значения, типы всех видов, и эти элементы могут быть определены public, protected или internal тоже.

Но при использовании модулей?

Я понял также, что модули, наконец, отображаются как классы в MSIL (промежуточный язык). Таким образом, модуль является классом, является типом.... Мощь моих сомнений улучшается....

При использовании модулей??? Полезны ли они?

Д. Syme также утверждает, что модули расширяемы, поэтому я предполагаю, что они подобны пространствам имен с этой точки зрения.

Я не могу понять причину их использования.

Thankyou

Ответ 1

Одно важное отличие:

. Пространства имен .NET не могут содержать значения (пусть определения), пока модули могут.

На уровне IL/Bytecode модуль компилируется в класс .net, а не в пространстве имен .net.

Когда использовать модули?

Для небольшой и конкретной задачи F # и другие FP обычно следуют схеме восходящего программирования: вы разлагаете свою задачу на набор небольших функций, а затем группируете эти функции в модуль.

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

В то время как пространство имен используется для группировки больших вещей: например, все классы для операций Матрицы.

Модуль не является статическим классом (в смысле С#) Модули могут содержать специальные значения F #, например. токарные функции; а статический класс не может.

Ответ 2

Как говорит Инь Чжу, модули могут содержать значения. И вы можете открывать такие модули, как пространства имен. Эти две функции вместе - вот почему в F # вы можете делать такие вещи, как

let z = max x y

тогда как на языке, подобном С#, вы всегда должны сказать что-то вроде

var z = Math.Max(x,y)
//      ^^^^^   can't call methods from elsewhere without a qualifier

и используйте квалифицированное имя (SomeClass.Method), а не просто имя (letBoundFunction). Поэтому вы можете использовать модули, когда хотите, чтобы люди могли открыть вам модуль Foo и называть bar, просто говоря bar, а не Foo.bar всюду. (Это особенно полезно для операторов, например, если вы определяете в библиотеке множество пользовательских операторов (таких как +++ или whatnot), помещая их в модуль, люди могут открыть модуль, а затем просто использовать, например, x +++ y, а не громоздкий материал вроде (Foo.+++) x y или что-то еще.)

Обратите внимание, что, хотя F # по умолчанию помещает код в файл .fs в модуле (с именем файла), вы можете изменить это, указав первый код в файле как объявление пространства имен, например

namespace Yadda
// declare some types or whatnot, they go in namespace Yadda

или объявив свой собственный модуль

module Blah
// stuff goes in Blah module

в верхней части файла.