DEV Community

Mariusz
Mariusz

Posted on

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

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"
Enter fullscreen mode Exit fullscreen mode

I added a new file I called Printer.fs

module Printer

let printString string =
    printfn "%s" string
Enter fullscreen mode Exit fullscreen mode

Then, I modified Program.fs

open Printer

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

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.
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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

Top comments (5)

Collapse
 
tunaxor profile image
Angel Daniel Munoz Gonzalez

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!

Collapse
 
francisl profile image
Francis Lavoie

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

Collapse
 
sduduzog profile image
Sdu

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

Collapse
 
klimcio profile image
Mariusz

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.

Collapse
 
klimcio profile image
Mariusz

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