简体   繁体   中英

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
  | [] -> []
  | h::t -> (h+1)::(add1 t) in List.fold_left add1 [1, 2, 3];;

Here's the 2nd try

 let a(b) =
let rec add1 = function
  | [] -> []
  | h::t -> (h+1)::(add1 t)
in 
let c = List.fold_left add1 b
in a [1,2,3];;

I think you should start with:

let add x = x + 1

And then build a function that applies a function to a list via List.fold_left:

let apply_f_to_list_elements fn lst = (*use List.fold_left here*)

Are you sure you want List.fold_left and not List.map?

As you seems to confuse map and fold_left I think this quote could help you to understand the difference:

"Imagine you have a big dinner with numerous people. You are serving the dish: you go through all the people and replace their empty plates with plates containing food. This is a map operation: the number of plate on the table didn't change, but for each plate, you have done the same action (changing the content of the plate). Once everything is done, you collect all the dirty plates: This is a fold operation, at the end, there are no more plates on the table, but you have done something for each plates (stacking them) and return the file result (a stack of dirty plates). In both case, an action is applied systmatically. The difference is that Map preserves the current "structure" (the plates on the table) while Fold removes the structure, and build something else."

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] 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 defined 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] 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
  fold_left f' [] lst |> 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM