How to improve this feature F #

I am experienced in C #, but new to F # and functional programming. Now I am trying to implement a class library in F #. Here is one of the functions: It takes a list of integers <= 9 and changes consecutive 9, for example, 9,9,9,9-9, 10, 11, 12. For example [9; nine; nine; 1; 4; 0; 1; nine; nine; nine; 9] will be changed to [9; 10; eleven; 1; 4; 0; 1; nine; 10; eleven; 12].

C # function is trivial:

void ReleaseCap(List<int> items)
{
    for (int i = 1; i < items.Count; i++)
    {
        var current = items[i];
        var previous = items[i - 1];
        //If curernt value = 9 and previous >=9, then current value should be previous+1
        if (current == 9 && previous >= 9)
        {
            items[i] = previous + 1;
        }
    }
}

Now my F # tail is recursive. Instead of quoting the list by index, it recursively moves the item from the original list to the processed list until everything in the original list disappears:

let releaseCap items =
    let rec loop processed remaining = //tail recursion
        match remaining with
        | [] -> processed //if nothing left, the job is done.
        | current :: rest when current = 9 -> //if current item =9
            match processed with
            // previous value >= 9, then append previous+1 to the processed list
            | previous :: _ when previous >= 9 -> loop (previous+1 :: processed) rest 
            //if previous < 9, the current one should be just 9
            | _ -> loop (current :: processed) rest 
        //otherwise, just put the current value to the processed list
        | current :: rest -> loop (current :: processed) rest 
    loop [] items |> List.rev

Although the C # version is trivial and intuitive, the F # code is verbose and not intuitive. Is there any part of the F # code that can be improved to make it more elegant?

+4
3

, . , , map, - , , fold.

: List.scan

let releaseCap items =
    items
        |> List.scan (fun previous current -> 
            if current = 9 && previous >= 9 then previous + 1
            else current) 0  
        |> List.tail

FP - . , .

. # F #, , ? # .

+5

# , .

F #, . .

   let reduceCap l = 
    let rec reduceCapRec acc l =
        let previous = List.head acc
        match l with
        | x::xs -> 
            if x = 9 && previous >= 9 
            then reduceCapRec ((previous+1) :: acc) xs
            else reduceCapRec (x :: acc) xs
        | [] -> acc

    reduceCapRec [List.head l] (List.tail l)
    |> List.rev

( Gustavo - FP)

+2

I thought fold was important !:-)

So:

let list = [9;9;9;1;4;0;1;9;9;9;9] 

let incr acc e =
    match acc, e with
    | h::t, e when e = 9 && h >= 9 -> (h + 1)::acc 
    | _ -> e::acc 


list 
|> List.fold incr []
|> List.rev

//val it : int list = [9; 10; 11; 1; 4; 0; 1; 9; 10; 11; 12]
+2
source

Source: https://habr.com/ru/post/1609376/


All Articles