Advent of Code 2018 day 1 part 2: find the first aggregated number that occures twice
It also looks functional to me, and I like your use of union type State.



You can define the Zero static member of State as:

type State =
    | FinalState of int
    | IntermediateState of int * int Set
    static member Zero = IntermediateState(0, Set.empty.Add(0)) 


You don't have to create a separate with-definition.



In general I avoid writing the result to the console in the algorithm function it self. Instead it is more useful to return the result and let the caller handle that as needed:

let rec processListRec state lst =
    let result = lst |&gt; Seq.fold foldState state
    match result with
    | FinalState result -&gt; result
    | IntermediateState _ -&gt; lst |&gt; processListRec result


Used as:

printfn "%A" (processListRec State.Zero input)




You need some kind of stop condition or an input check if all changes are positive or negative.

For instance will [1;1;1] run forever, because no frequency will ever occur twice.



A raw recursive solution could be:

let findReoccurantFrequency input = 
    if (input |&gt; List.groupBy (fun x -&gt; x &gt; 0)) |&gt; List.length &lt; 2 then 
        raise (Exception "Invalid input (only positive or negative changes)")
    else
        let rec runner lst freq freqs =
            if freqs |&gt; List.contains freq then
                freq
            else
                let head, tail = if lst = [] then input.Head, input.Tail else lst.Head, lst.Tail
                runner tail (freq + head) (freq::freqs)
        runner input 0 []


I'm not saying that it's a better solution, just another approach for the exercise and inspiration. Especially I'm not proud of the input check.



Edit

As pointed out by JanDotNet in his comment, my input validation is poor, so it's maybe better to leave it out. Below is a revised version of my implementation using a Set instead of a List for the frequencies:

let findReoccurantFrequency input = 
    let rec runner lst freq freqs =
        match freqs |&gt; Set.contains freq with
        | true -&gt; freq
        | false -&gt;
            let head, tail = if lst = [] then input |&gt; List.head, input |&gt; List.tail else lst.Head, lst.Tail
            runner tail (freq + head) (freqs.Add(freq))
    runner input 0 Set.empty