ocaml

# What's wrong with my attempt to add 1 to every element in my list in Ocaml?

I don't understand the error message I'm getting or what's wrong with what I'm trying to do

I just want to use List.fold_left to apply my add1 function to this list [1,2,3]

My add1 function should just add 1 to each element, so I would get [2, 3, 4]

My main goal in doing this exercise is just to experiment with List.fold_left. I don't actually care about adding 1, I just choose that function because it seemed easy to write (I'm an ocaml beginner).

My ultimate goal is actually to populate the keys of a empty StringMap using List.fold_left and a function already written elsewhere, so if anyone has insight on that it would also be appreciated

Here's the 1st try (which I tried twice)

``````let rec add1 = function
| [] -> []
``````

Here's the 2nd try

`````` let a(b) =
| [] -> []
in
let c = List.fold_left add1 b
in a [1,2,3];;
``````

Solution

• It may help you to see how `fold_left` can be implemented.

``````let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
``````

So consider what's happening when something like a sum function works, when implemented in term of `fold_left`.

``````let sum lst =
fold_left (+) 0 lst
``````

If we evaluate `sum [1; 2; 3; 4]`:

``````sum [1; 2; 3; 4]
fold_left (+) 0 [1; 2; 3; 4]
fold_left (+) (0 + 1) [2; 3; 4]
fold_left (+) (1 + 2) [3; 4]
fold_left (+) (3 + 3) [4]
fold_left (+) (6 + 4) []
10
``````

We can define `map` in terms of `fold_left`:

``````let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst
``````

Let's evaluate `map (fun x -> x + 1) [5; 2; 6]`:

``````map (fun x -> x + 1) [5; 2; 6]
fold_left f' [] [5; 2; 6]
fold_left f' (5 + 1 :: []) [2; 6]
fold_left f' (2 + 1 :: [6]) [6]
fold_left f' (6 + 1 :: [3; 6]) []
[7; 3; 6]
``````

Now, because of the way we destructure and create lists, the result is backwards. we can overcome this with `fold_left` by reversing the resulting list.

``````let map f lst =
let f' init x = f x :: init in
let lst' = fold_left f' [] lst in
List.rev lst'
``````

Or with the `|>` operator:

``````let map f lst =
let f' init x = f x :: init in
lst |> fold_left f' [] |> List.rev
``````

## Taking this to the next level

At each iteration, `fold_left` transforms the first element in a list and an accumulator, into the accumulator for the next iteration. If you want to apply this concept to your `StringMap` module, consider `StringMap.empty` which generates an empty `StringMap.t`, and `StringMap.add` which take a key, an associated value, and an existing map, and returns a new map with that added mapping.

You can readily use `fold_left` to take an initially empty map and build it into a complete map step by step. The only question remaining will be what value you choose to associate with each string in your list.