Compile F# to Morphir IR
Acme Car Rental keeps its daily rates in F#. In five minutes you turn that rule into Morphir IR, and then into C# that another team can call.
graph LR
A[Rates.fs] -->|dotnet-morphir compile| B[morphir-ir.json]
B -->|dotnet-morphir generate| C[C# or F# code]1. Install the tool
You need the .NET SDK 10.0 or later.
dotnet tool install --global Morphir.Tool --prerelease
dotnet-morphir --version
2. Write the rule
mkdir -p acme/src && cd acme
Save this as src/Rates.fs:
namespace Acme.CarRental
module Rates =
type VehicleClass =
| Economy
| Compact
| Suv
let dailyRate (vehicle: VehicleClass) : int =
match vehicle with
| Economy -> 4000
| Compact -> 5000
| Suv -> 8000
3. Compile it
dotnet-morphir compile --language fsharp --input src/Rates.fs --package-name acme/car-rental
compile succeeded: 1 module(s), IR version 4, /work/acme/.morphir/out/compile.dest/morphir-ir.json; no diagnostics
/work/acme/.morphir/out/compile.dest/morphir-ir.json
The IR is in .morphir/out/compile.dest/morphir-ir.json. Every later command can find it there.
4. Generate code
dotnet-morphir generate --target csharp --output generated/csharp
p_Acme.CarRental/m_RatesModule.g.cs
generate reads the IR of the most recent compile, so it needs no --input. Use
--target fsharp for F#.
Do both steps in one run:
dotnet-morphir compile --language fsharp --input src/Rates.fs --package-name acme/car-rental \
--target csharp --generate-output generated/csharp
Compile without .NET installed
The native morphir executable has no built-in F# frontend. It starts the F#
frontend as a separate process. The frontend has a self-contained delivery: a
folder with the frontend, the F# compiler service and its own .NET runtime.
With it, compiling F# needs no .NET SDK, no .NET runtime and no dotnet
command on the machine.
Releases do not publish this folder yet. Build it from a checkout, on a machine with the .NET SDK, for the runtime identifier of the target machine:
dotnet publish src/Morphir.Frontend.FSharp.Extension -c Release -r win-arm64 -p:PublishProfile=SelfContainedProcess -p:MorphirRidSpecificPublish=true -o morphir-fsharp-frontend
MorphirRidSpecificPublish=true writes the publish’s lock files under obj/,
so the committed packages.lock.json files do not change. The build target
PublishFSharpFrontendProcess --rid <rid> publishes the same folder, a zip
(Windows) or .tar.gz archive of it with the files at the archive root, and
the publish’s lock file beside the archive. Copy the folder to the
target machine and name its executable with --extension:
morphir compile --language fsharp --input src/Rates.fs --package-name acme/car-rental --extension "C:\Tools\morphir-fsharp-frontend\morphir-fsharp-frontend.exe"
What this supports: compiling supported F# source files (--input) of one
package to Morphir IR. The compiler references are only the .NET framework,
FSharp.Core and Morphir.FSharp.Annotations; there is no NuGet restore and no
reference to another package or assembly. It is not a build of an arbitrary
.fsproj, and it does not compile the generated code: building an
application from generated F# or C# still needs the .NET SDK.
Checked on Windows 11 ARM64 (win-arm64), on a machine with .NET installed
but hidden from the frontend: the folder runs from a path with a space, with no
dotnet on PATH, no DOTNET_* variables, no global install and an empty
NuGet packages folder. It loads the .NET runtime from its own folder, and at
the same runtime version it gives the same IR and diagnostics as the
framework-dependent Morphir.Frontend.FSharp.Extension tool. It was not run
on a machine with no .NET at all. The other platforms are not qualified yet; see
Installation.
Next steps
- Tutorial: car rental pricing from F# to C#: a project file, three modules, a refused construct, a C# app and a CI check.
- Tutorial: compile F# with the native executable:
the AOT
morphirand the F# frontend extension. - What F# can you write?
compilereference
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.