Структура F#-проекта
Чем F#-проект отличается от C#
В C# порядок файлов в .csproj почти не важен: класс из B.cs видит класс из A.cs в том же проекте.
В F# компилятор обрабатывает файлы строго в порядке, указанном в .fsproj (или в порядке по умолчанию SDK, пока вы не добавили свои файлы). Код в файле может использовать только то, что объявлено:
- в предыдущих файлах проекта, или
- выше по тексту в том же файле.
Типичная ошибка:
error FS0039: The value, namespace, type or module 'Order' is not defined.
Частая причина — Program.fs стоит выше Domain.fs, хотя Program ссылается на тип Order из Domain.
Словарь файлов проекта
| Файл | Назначение |
|---|---|
.fsproj | Манифест проекта: целевой framework, список .fs, ссылки на пакеты и проекты |
.fs | Исходник F# |
.fsi | Файл подписи (интерфейс): видимые снаружи сигнатуры без реализации |
Program.fs | Обычно точка входа консольного приложения |
.sln | Solution — несколько проектов (библиотека + приложение + тесты) |
Минимальный консольный проект
dotnet new console -lang F# -n DemoApp
cd DemoApp
dotnet run
Структура:
DemoApp/
DemoApp.fsproj
Program.fs
В простом шаблоне один файл — порядок очевиден. Как только появляется второй .fs, порядок нужно контролировать явно.
Явный порядок в .fsproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Domain.fs" />
<Compile Include="Services.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
</Project>
Рекомендуемое содержимое слоёв:
| Файл | Что держать |
|---|---|
Domain.fs | типы, DU, записи, чистые функции без I/O |
Services.fs | оркестрация, HTTP, БД, файлы |
Program.fs | [<EntryPoint>], меню, композиция, dotnet run |
Правило: от данных к эффектам, от общего к частному. Так зависимости читаются сверху вниз в .fsproj.
Пример Domain.fs:
module DemoApp.Domain
type OrderId = OrderId of int
type Order = { Id: OrderId; Amount: decimal }
Services.fs:
module DemoApp.Services
open DemoApp.Domain
let describe (Order { Id = OrderId n; Amount = a }) =
$"Order {n}, amount {a}"
Program.fs вызывает Services.describe — оба модуля уже скомпилированы выше.
Библиотека и ссылка из приложения
dotnet new classlib -lang F# -n DemoLib
dotnet new console -lang F# -n DemoApp
dotnet add DemoApp/DemoApp.fsproj reference DemoLib/DemoLib.fsproj
В DemoLib.fsproj:
<ItemGroup>
<Compile Include="Types.fs" />
<Compile Include="Api.fs" />
</ItemGroup>
В приложении:
open DemoLib
Имя модуля по умолчанию совпадает с именем файла (Types, Api) или задаётся через module MyName = в начале файла. Для C#-клиентов: [<CLIMutable>] на DTO, осмысленные имена, при конфликтах — [<RequireQualifiedAccess>] на модуле.
Модули, namespace и один файл
namespace MyCompany.Demo
module Domain =
type Id = Id of int
module Services =
open Domain
let format (Id n) = $"#{n}"
namespace— префикс имён для CLR.module— группа функций и типов; полное имя может бытьMyCompany.Demo.Domain.- В файле с
namespaceвесь код верхнего уровня должен быть внутриmoduleилиtype.
Несколько module в одном файле компилируются сверху вниз; при сложных зависимостях проще разнести модули по разным .fs.
Файлы подписей .fsi
Пара:
Domain.fsi — только сигнатуры (контракт)
Domain.fs — реализация
В .fsproj .fsi строго перед .fs:
<Compile Include="Domain.fsi" />
<Compile Include="Domain.fs" />
Клиент библиотеки видит только то, что в .fsi; детали реализации скрыты. Полезно для публичных NuGet-пакетов на F#.
Solution из нескольких проектов
src/
App.Core/ # F# — домен
App.Infrastructure/ # F# или C# — БД, файлы
App.Web/ # ASP.NET Core (часто C#)
tests/
App.Core.Tests/
У каждого .fsproj свой порядок <Compile Include="..."/>. Смешанный solution (C# UI + F# core) распространён: F# собирается в DLL, C# добавляет <ProjectReference> — без специальных флагов, кроме продуманного публичного API.
Связь с FSI и #load
Скрипт:
#load "Domain.fs"
#load "Services.fs"
Порядок #load должен повторять порядок в .fsproj. Иначе в REPL та же FS0039, что и при сборке.
См. Интерактивная работа (FSI).
Частые проблемы
| Симптом | Что проверить |
|---|---|
| FS0039 — имя не найдено | Поднять файл с определением выше в .fsproj |
| Циклическая зависимость двух файлов | Вынести общие типы в третий файл или объединить модули |
| Два модуля с одним именем | Разные namespace или RequireQualifiedAccess |
| IntelliSense пустой | Успешный dotnet build (Ionide опирается на компилятор) |
Тест не видит internal | InternalsVisibleTo в .fsproj библиотеки |
Сборка и проверка
dotnet build
dotnet test
dotnet run --project src/DemoApp/DemoApp.fsproj
Предупреждения компилятора (--warnon) задают в <OtherFlags> — см. Справочник по F#.
Маршрут обучения F# в разделе
- F# в экосистеме .NET
- Первая программа
- Интерактивная работа (FSI)
- Сопоставление с образцом
- Императивные конструкции · ООП для interop · Асинхронность
- Структура проекта (эта статья)
- Справочник по F# · Справочник Learn
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Платформа .NET - архитектура экосистемы, инструменты разработки и модель выполнения приложений. Эти механизмы позволили реализовать фундаментальный принцип .NET — язык — это синтаксический фасад над общей семантикой CLR. Понимание архитектуры .NET невозможно без хронологического контекста, поскольку многие текущие решения — это результат многолетней итеративной оптимизации. Типы приложений на платформе .NET - веб, desktop, мобильные и облачные сценарии в единой экосистеме. Сборка и развёртывание .NET-приложений - артефакты, среды выполнения и практики доставки в продакшен. Пакеты и зависимости в .NET - управление версиями, восстановление пакетов и интеграция в процесс сборки. В Visual Studio проект — это единица сборки — он определяет, что и как компилируется. Проект содержит .csproj, исходные файлы, ресурсы и метаданные зависимостей. NuGet - система управления пакетами .NET для публикации, версионирования и подключения зависимостей. ADO.NET в .NET 8+ — Connection, Command, параметры и провайдеры; краткая история классического ADO (COM). ASP.NET - веб-платформа Microsoft для разработки серверных приложений, API и динамических сайтов. Экосистема .NET-приложений - поддерживаемые платформы, сценарии разработки и интеграция с современными устройствами. F# в экосистеме .NET - функциональный стиль, совместимость с платформой и применение в прикладной разработке.Платформа .NET
История платформы .NET
Архитектурные особенности .NET
Типы приложений на платформе .NET
Сборка и развёртывание .NET-приложений
Пакеты и зависимости в .NET
Инструменты разработки для .NET
NuGet - система управления пакетами
ADO.NET - доступ к данным
ASP.NET - веб-платформа Microsoft
Экосистема .NET-приложений
F# - функциональный язык в экосистеме .NET