loading...

File Order in F# - the most annoying thing for a beginner?

klimcio profile image Mariusz ・2 min read

Back to learning F#. Recently, I learned something that is most probably the most annoying thing so far. It looks very discouraging seeing tutorials where people are reordering files in Visual Studio just to make everything compile.

I had to see it with my own eyes :-)

Using VSCode and .NET Core 3.1 I created a small project

dotnet new console -lang F# -o "05 Modules"

I added a new file I called Printer.fs

module Printer

let printString string =
    printfn "%s" string

Then, I modified Program.fs

open Printer

[<EntryPoint>]
let main argv =
    printString "1"
    0 // return an integer exit code

And then I run using dotnet run.

The first thing I learned when adding a new file is that you must declare modules for F# files. The error message says, something more:

error FS0222: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.

Which means that Program.fs does not need a module. Or does it?

When I added the new file into fsproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RootNamespace>_05_Modules</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
    <Compile Include="Printer.fs" />
  </ItemGroup>

</Project>

And I must confess, I added the last file Printer.fs manually. At the end, where else? ;-)

Depending on what is going on in the project, I got two different errors. At first I got:

error FS0222: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.

At first I tried to add module Program inside Program.fs, I thought it has given me new errors, therefore progress (see the end of the post, as this was not a solution):

error FS0039: The namespace or module 'Printer' is not defined. Maybe you want one of the following:↔   Printf↔   PrintfModule

error FS0039: The value or constructor 'printArray' is not defined. Maybe you want one of the following:↔   printf↔   Printf↔   printfn↔   PrintfFormat

What else can be missing? The file is mentioned in fsproj, it has a module, it is referenced by Program.fs.

Well, here's the annoying frustrating part: file order.

When I switched the file order in fsproj to

  <ItemGroup>
    <Compile Include="Printer.fs" />
    <Compile Include="Program.fs" />
  </ItemGroup>

It compiled and run.

Yes, that is a language feature :-)

PS. After making that program compile I removed module Program from Program.fs and it still worked. As the error message said: Program does not need to be in a module.

This blog post was first published on my blog

Discussion

pic
Editor guide
 

I don't recommend editing the fsproj files by hand. If you use Ionide (and you should if you're doing F# with VSCode) you can rearrange files with the little arrow keys next to the file name:

ionide

 

I don't know if I'm alone with that issue, but I stop using it at one point, because it was most of the time unresponsive. Also when I have folders to group up files, then there is no way to order them except the fsproj file

 

Thanks, Michael. Still learning, so this is very helpful :-)

 

If you're still learning, keep an eye out for the next round of the F# mentorship program:

fsharp.org/mentorship/index.html

You need to be an FSSF member to participate, but the basic free membership is enough. I've participated as both mentee and mentor and it's a great program.

 

Ah yes, the at first not wonderful File Order. I admit I left F# the first 3-5 attempts because I was so used to not having to order my files that was incredibly annoying... but after some usage and some wonderful bugs (cyclic dependencies :P) in other languages I was working on I started to actually love file ordering and the fact that If I ever needed to check a type, function module, etc. it was going to be always declared in a previous file, that made way easier to reason over the code I was writing and exploring in the wild

cheers on your F# trip!

 

I'll take a wild guess and say 'Program.fs' contains code that tries to execute something in 'Printer.fs'. It tecknically makes sense for a functional language to behave this way but still that is just so many configuration elements to keep note of. I wanna start learning F# soon but I don't have a project for it yet

 

You can always use it for tasks found on spoj just to see what and how can be achieved in a language. I know I'll be doing it, once I learn F# long enough to do some small projects on my own.