Beginner question. Problem with including module

Hey, sorry in advance if this is the wrong place for this topic.

So I am new to F# and and currently playing around with a toy project. I installed F# with .NET Core and am using the Ionide-Fsharp extension for VS Code. I have also installed the Argu package in order to parse command line options. I would now like to move the functionality for parsing to a separate file rather than my Program.fs file if that makes sense.

My code works as intended if placed in Program.fs as follows:

module CLI =
    open Argu

    type CliArguments =
    | [<Mandatory; AltCommandLine("-i")>]  Instance of string 
    | [<CustomCommandLine("-a", "--all")>] All   
    | [<CustomCommandLine("-v", "--verbose");>] Verbose    
        interface IArgParserTemplate with
            member s.Usage = match s with
                | Instance _ -> "input DIMACS file."
                | All _      -> "exhaustive search?"
                | Verbose _  -> "turn verbose mode on"
       
    let parser = ArgumentParser.Create<CliArguments>(programName = "gadget.exe")

[<EntryPoint>]
let main argv =
    let results = CLI.parser.ParseCommandLine argv
    printfn "Got parse results %A" <| results.GetAllResults()
    0

If I try to move this parsing logic to a seperate file CLI.fs, the package Argu is not found within CLI.fs, and the CLI module is not found within Program.fs.

CLI.fs:

module CLI =

    open Argu

    type CliArguments =
    | [<Mandatory; AltCommandLine("-i")>]  Instance of string
    | [<CustomCommandLine("-a", "--all")>] All
    | [<CustomCommandLine("-v", "--verbose");>] Verbose
        interface IArgParserTemplate with
            member s.Usage =
                match s with
                | Instance _ -> "input DIMACS file."
                | All _      -> "exhaustive search?"
                | Verbose _  -> "turn verbose mode on"

    let parser = ArgumentParser.Create<CliArguments>(programName = "gadget.exe")

Program.fs:

[<EntryPoint>]
let main argv =
    let results = CLI.parser.ParseCommandLine argv
    printfn "Got parse results %A" <| results.GetAllResults()
    0

Any ideas on how I should go about this? :slight_smile:

OK so turned out I had to add the CLI.fs file to the item group of compiled files in my .fsproj file.

Also, removing the “=” and indentation in CLI.fs was necessary.

CLI.fs:

module CLI

open Argu

type CliArguments =
| [<Mandatory; AltCommandLine("-i")>]  Instance of string
| [<CustomCommandLine("-a", "--all")>] All
| [<CustomCommandLine("-v", "--verbose");>] Verbose
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | Instance _ -> "input DIMACS file."
            | All _      -> "exhaustive search?"
            | Verbose _  -> "turn verbose mode on"

let parser = ArgumentParser.Create<CliArguments>(programName = "gadget.exe")

Program.fs:

open CLI

[<EntryPoint>]
let main argv =
    let results = CLI.parser.ParseCommandLine argv
    printfn "Got parse results %A" <| results.GetAllResults()
    0
1 Like

That’s a good start. It is only the last module that can omit the module declaration at the top (I.e. Program). And it’s only nested modules that need to be indented with the equals sign.
It is also nice that you don’t have any namespace declaration. I think you won’t need that unless you build something that should be shared (I.e. a library you publish). Using only modules is much more concise. Finally, I am also a fan of Argu!

1 Like