Skip to content

Instantly share code, notes, and snippets.

@BashkaMen
Last active April 16, 2020 11:58
Show Gist options
  • Save BashkaMen/cb3347278ac3fc1ac2e2b5d721b44a0f to your computer and use it in GitHub Desktop.
Save BashkaMen/cb3347278ac3fc1ac2e2b5d721b44a0f to your computer and use it in GitHub Desktop.
open System
type Id = int
type TodoValue =
| Text of string
| Markdown of string
| Html of string
//type UnCompleteTodo =
// { Id: Id
// Value: TodoValue }
//
//type CompletedTodo =
// { Id: Id
// Value: TodoValue }
type Todo =
| UnCompleted of {| Id: Id; Value: TodoValue |}
| Completed of {| Id: Id; Value: TodoValue |}
type Command =
| Create of {| Value: string |}
| Remove of {| Id: Id |}
| Complete of {| Id: Id |}
type State = Todo list
let r = Random()
let update state cmd =
let getId = function
| UnCompleted s -> s.Id
| Completed s -> s.Id
let getValue = function
| UnCompleted s -> s.Value
| Completed s -> s.Value
match cmd with
| Create c -> state @ [ UnCompleted {| Id = r.Next(10); Value = Text c.Value |} ]
| Remove r -> state |> List.filter (fun s -> getId s <> r.Id)
| Complete complete ->
let found = state |> List.find (fun s -> getId s = complete.Id)
let completed = Completed {| Id = getId found; Value = getValue found |}
state
|> List.filter (fun s -> getId s <> complete.Id)
|> List.append [ completed ]
let view state =
state |> sprintf "STATE: %A"
let rec getCmd() =
printf "enter cmd: "
let input = Console.ReadLine()
match input with
| "create" ->
printf "enter todo value: "
Create {| Value = Console.ReadLine() |}
| "remove" ->
printf "enter todo id for remove: "
Remove {| Id = Int32.Parse(Console.ReadLine()) |}
| "complete" ->
printf "enter todo id for complete: "
Complete {| Id = Int32.Parse(Console.ReadLine()) |}
| _ ->
printfn "invalid command, try again"
getCmd()
let rec appLoop state =
let newState = getCmd() |> update state
printfn "%s" (view newState)
appLoop newState
let initState = list<Todo>.Empty
[<EntryPoint>]
let main argv =
appLoop initState
0 // return an integer exit code
@Szer
Copy link

Szer commented Apr 16, 2020

open System
open System.Collections.Generic

type Id = int



type TodoValue =
    | Text of string
    | Markdown of string
    | Html of string


type UnCompleteTodo =
    { Id: Id
      Value: TodoValue }


type CompletedTodo =
    { Id: Id
      Value: TodoValue }

type Todo =
    | UnCompleted of UnCompleteTodo
    | Completed of CompletedTodo
    member x.Id =
        match x with
        | UnCompleted { Id = id } -> id
        |   Completed { Id = id } -> id
    member x.Value =
        match x with
        | UnCompleted { Value = v } -> v
        |   Completed { Value = v } -> v
    static member NewUncompleted =
        let random = Random()
        fun value ->
            UnCompleted { Id = random.Next(10)
                          Value = value }
    member x.Complete() =
        match x with
        | Completed _ -> x
        | UnCompleted todo ->
            Completed { Id = todo.Id; Value = todo.Value }

type Command =
    | Create of value: string
    | Remove of id: Id
    | Complete of id: Id

type State = SortedDictionary<Id,Todo>
[<RequireQualifiedAccess>]
module State =
    
    let add (todo: Todo) (state: State) =
        state.Add(todo.Id, todo)
        state
    
    let remove key (state: State) =
        state.Remove key |> ignore
        state
        
    let find key (state: State) =
        match state.TryGetValue key with
        | true, v -> Some v
        | _ -> None
        
    let get key (state: State) = state.[key]
    
    let complete key (state: State) =
        let found = get key state
        let completed = found.Complete()
        if completed = found then
            state
        else
            state
            |> remove key
            |> add completed
    
let update (state: State) cmd =
        
    match cmd with
    | Create todoText ->
        let newTodo = Todo.NewUncompleted (Text todoText)
        State.add newTodo state
    | Remove id ->
        State.remove id state
    | Complete id ->
        State.complete id state

let view state =
    state |> sprintf "STATE: %A" 

let rec getCmd() =
    printf "enter cmd: "
    let input = Console.ReadLine()
    match input with
    | "create" ->
        printf "enter todo value: "
        Create (value = Console.ReadLine())
    | "remove" ->
        printf "enter todo id for remove: "
        Remove (id = Int32.Parse(Console.ReadLine()))
    | "complete" ->
        printf "enter todo id for complete: "
        Complete (id = Int32.Parse(Console.ReadLine()))
    | _ ->
        printfn "invalid command, try again"
        getCmd()


let rec appLoop state =
    let newState = getCmd() |> update state
    printfn "%s" (view newState)
    appLoop newState

let initState = State()

[<EntryPoint>]
let main argv =
    appLoop initState
    
    0 // return an integer exit code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment