# Basic F# console UI program loop

**URL:** <https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216>\
**Category:** General\
**Tags:** beginners\
**Created:** [March 2, 2020, 1:58am UTC](https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216 "2020-03-02T01:58:15Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![IvanRainbolt](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/ivanrainbolt/32/716_2.png) [@IvanRainbolt](https://forums.fsharp.org/u/IvanRainbolt)\
**Post date:** [March 2, 2020, 1:58am UTC](https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216/1 "2020-03-02T01:58:15Z")

</div>

I desperately want to create great and useful programs for myself and others. I am focused on F# and eventually Azure. I want to focus on the “mechanics” of the program first. In doing so, I want to create a super simple “UI”, a basic _“do this”_ and show me the result. Then let me _“do that”_ and show me the result. A console app seems best to me.

Does the following seem to be a good start? Suggestions?  
[GIST](https://gist.github.com/IvanRainbolt/6bddae9e59a52312e675afc7d5d76529)

```
open System

let printPrompt () = 
    printf "command:>"

let getCommandLineInput _ =  
    printPrompt ()
    System.Console.ReadLine ()

let writeError value =
    printfn "ERROR - No Match\nYou typed: %s" value

let writeMatch value =
    printfn "Matched: %s" value
 
let processCommandLineInput commandLineInput =
    match commandLineInput with
    | "a" -> writeMatch "a" 
    | "b" -> writeMatch "b" 
    | "exit" -> Environment.Exit 55
    | "quit" -> Environment.Exit 55
    | _ -> writeError commandLineInput 
    //change to output a 'command'?

let progLoop () =
    let commandLineInput = Seq.initInfinite getCommandLineInput
    Seq.iter processCommandLineInput commandLineInput
    
[<EntryPoint>]
let main argv = 
    progLoop () 
    0
```

---

<div class="post-metadata">

**Author:** ![FoggyFinder](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/foggyfinder/32/136_2.png) [@FoggyFinder](https://forums.fsharp.org/u/FoggyFinder)\
**Post date:** [March 3, 2020, 7:57am UTC](https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216/2 "2020-03-03T07:57:10Z")

</div>

1. You probably might consider option to change color of the message depending on its type (Error, General, Success).

[Console.BackgroundColor](https://docs.microsoft.com/en-us/dotnet/api/system.console.backgroundcolor)

1. In case when you have exactly the same action that performed by different patterns (“quit”, “exit”) you can combine them via “|”

```auto
| "a" | "b" as v -> writeMatch v
| "exit" | "quit" -> Environment.Exit 55

```

1. You can use pipe-forward operator inside of the `progLoop`:

```auto
let progLoop () =
    getCommandLineInput
    |> Seq.initInfinite
    |> Seq.iter processCommandLineInput

```

---

<div class="post-metadata">

**Author:** ![IvanRainbolt](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/ivanrainbolt/32/716_2.png) [@IvanRainbolt](https://forums.fsharp.org/u/IvanRainbolt)\
**Post date:** [March 4, 2020, 4:33pm UTC](https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216/3 "2020-03-04T16:33:22Z")

</div>

Thank you.

1. The colors is a great idea, that is more fluff than I am willing to invest at this stage 🙂 I would expect that to be a future upgrade though.
2. This is really helpful. I actually had tried` "exit" || "quit"` and of course that didn’t work. Now I see the correct way. TY.
3. Seeing this and being able to compare it gives me great insight. Again. Thank you.  
I updated the [GIST](https://gist.github.com/IvanRainbolt/6bddae9e59a52312e675afc7d5d76529)

So given the updated program:

```
//Very basic F# command line UI 
//trying to get a global state

open System

let mutable x = "NoUser"

let printPrompt () = 
    printfn "Current State: %s" x
    printf "command:>"

let getCommandLineInput _ =  
    printPrompt ()
    System.Console.ReadLine ()

let writeError value =
    printfn "ERROR - No Match\nYou typed: %s" value

let writeMatch value =
    printfn "Matched: %s" value
 
let processCommandLineInput commandLineInput =
    match commandLineInput with
    | "a" -> writeMatch "a"; x <- "Ivan"
    | "b" -> writeMatch "b"; x <- "Bob" 
    | "c" -> writeMatch "b" 
    | "exit" | "quit" -> Environment.Exit 55
    | _ -> writeError commandLineInput 
    //change to output a 'command'?

//let progLoop () =
// let commandLineInput = Seq.initInfinite getCommandLineInput
// Seq.iter processCommandLineInput commandLineInput
    
let progLoop () =
    getCommandLineInput
    |> Seq.initInfinite
    |> Seq.iter processCommandLineInput

[<EntryPoint>]
let main argv = 
    progLoop () 
    0

```

I am stuck on updating state without the mutable. My thought is I need to pass the current state through the interactions, but I am not getting it figured out. So the process would be program starts, initial state is set. If I do a particular function, it can create a new state (updated) state and pass it along as the new current state for the next iteration. This is like the Elmish idea. I am just not seeing where to pass and pickup the state in each iteration. Any suggestions?

---

<div class="post-metadata">

**Author:** ![FoggyFinder](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/foggyfinder/32/136_2.png) [@FoggyFinder](https://forums.fsharp.org/u/FoggyFinder)\
**Post date:** [March 4, 2020, 5:32pm UTC](https://forums.fsharp.org/t/basic-f-console-ui-program-loop/1216/4 "2020-03-04T17:32:49Z")

</div>

Then I suppose it would be easier to use simple recursive function.

```auto
open System

let printPrompt state = 
    printfn "Current State: %s" state
    printf "command:>"

let getCommandLineInput = Console.ReadLine

let writeError value =
    printfn "ERROR - No Match\nYou typed: %s" value

let writeMatch value =
    printfn "Matched: %s" value
 
let processCommandLineInput state commandLineInput =
    match commandLineInput with
    | "a" -> writeMatch "a"; Some "Ivan"
    | "b" -> writeMatch "b"; Some "Bob"
    | "c" -> writeMatch "c"; Some state
    | "exit" | "quit" -> None
    | _ -> writeError commandLineInput; Some state

let rec progLoop state =
    state |> printPrompt
    let updated = 
        getCommandLineInput()
        |> processCommandLineInput state
    match updated with
    | Some newState -> progLoop newState
    | None -> Environment.Exit 55

[<EntryPoint>]
let main argv = 
    "NoUser" |> progLoop 
    0

```
