🔖

【F#】パスにファイルが存在しなかったらコンパイルエラーにする

2022/11/13に公開

概要

F#にはTypeProviderというものがあり、面倒なコード生成無しにコンパイル時にごにょごにょする機能が用意されています。

今回はこちらのパッケージを使用させていただきます。
Tarmil/FSharp.Data.LiteralProviders

TextFileEnsureExistsパラメータを利用することで、指定したパスにファイルが存在しなければコンパイルエラーとなります。(本来はテキストファイルの中身を読み取る TypeProvider ですが)

以前お願いしたら実装して頂けました。やったー。

具体例

コード

Path.fs

module Path
let [<Literal>] Image1 = "Images/Image1.png"
let [<Literal>] Image2 = "Images/Image2.png"
let [<Literal>] Sound1 = "Sounds/Sound1.ogg"

#if DEBUG
module private EnsureFilePath =
  open FSharp.Data.LiteralProviders
  let [<Literal>] Base = "../../Resources/"

  do
    ignore typeof<
      TextFile<const (Base + Image1), EnsureExists=true> *
      TextFile<const (Base + Image2), EnsureExists=true> *
      TextFile<const (Base + Sound1), EnsureExists=true>
    >
#endif

TypeProvider に渡すので、パスはLiteralAttributeを付けます。constキーワードを使って、 TypeProvider の引数内でパスの結合ができます。今回はTextFileで作られた型自体は必要ないので、ignore typeof< (* ... *) >として捨てています。

プロジェクトファイル

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Path.fs" />
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup Condition="'$(Configuration)'=='Debug'">
    <PackageReference Include="FSharp.Data.LiteralProviders" Version="1.0.3" />
  </ItemGroup>
</Project>

DEBUGビルド時のみパッケージを参照しています。

プロジェクトの構造

EnsureExistsExample
|--Resources
|  |--Images
|  |  |--Image1.png
|  |  |--Image2.png
|  |--Sounds
|  |  |--Sound1.png
|--src
|  |--Example
|  |  |--Example.csproj
|  |  |--Path.fs
|  |  |--Program.fs

TextFileに与えた相対パスはプロジェクトファイルから参照されます。

Discussion