0

I am trying to take a desired number of elements out of an input list in OCAML. For example, I call my function as "take" which takes two parameters "my_list" and "x". Here it is:

let take my_list x =
    let accum = ([],[],0) in
    let f (all_groups, current_group, size) x = 
            if size then ((List.rev current_group)::(all_groups),[x],1)
            else (all_groups, x::current_group,size + 1) in
        let (groups,last,_) = List.fold_left f acc lst in
                  List.rev(List.rev last::group)

I got a type error:

This expression has type bool but an expression was expected of type int Why is this the case?

I am guessing there is something I need to do with my if...else statement. My reason is that if the desired number of elements I want to take out of my list is true (i.e implement this code if I want to take 3 elements out of the list, no 2), then proceed. Otherwise, keep adding the elements to the current list until it is filled with the desired number of elements I want to take out.

Thank you for any input.

glennsl
  • 28,186
  • 12
  • 57
  • 75
John Dunn
  • 11
  • 6
  • `if size then` it's not a C, try `if size <> 0 then`, also in `List.fold_left f acc lst` it's not `acc` but `accum` and `lst` is `x`, I guess – vonaka Feb 11 '18 at 17:23
  • `List.rev(List.rev last::group)` - `groups` not `group`. Yeh, pretty buggy code – vonaka Feb 11 '18 at 17:29
  • @vonaka I fixed that but the input was odd:take 3 [1;2;3;4;5;6;7];; - : int list list = [[1]; [2]; [3]; [4]; [5]; [6]; [7]] – John Dunn Feb 11 '18 at 19:58
  • @JohnDunn I've rolled back the question to its original state, so that the answer given still makes sense. Please don't change the meaning of the question after an answer has been given. Make a new question instead. Also, please go through the [tour]. – glennsl Feb 12 '18 at 16:50

1 Answers1

0

Let's start with your typing problem. Because of if size then ... size get's typed as bool because it appears as a condition in an if expression. Later on you try to add 1 to it. This is not possible with bools, so the interpreter complains. You don't actually want size to be a bool, so you should check the following.

if size >= x then ...

To be able to do this you should not overshadow the x argument of take with the list argument of f. I suggest that you rename the argument of take to n or something like that and then test for

if size >= n then

You also need to supply accum and my_list to fold_left instead of non existing arguments acc and lst.

In the end you should end up with this which I think works as intended:

let take my_list n =
    let accum = ([],[],0) in
    let f (all_groups,current_group, size) x =
            if size >= n then ((List.rev current_group)::all_groups,[x],1) else (all_groups,x::current_group,size+1)
    in let (groups, last, _) = List.fold_left f accum my_list in
    List.rev((List.rev last)::groups)
Rincewind
  • 197
  • 1
  • 1
  • 9
  • I think I have found out something else. Once I extract the number of elements I want, I am done. That is what I want. And I am still stuck. – John Dunn Feb 11 '18 at 22:53
  • 1
    @JohnDunn Please avoid changing your question after people have already answered. If you have a new question, feel free to post a new one – Nick Zuber Feb 12 '18 at 14:46
  • @JohnDunn Please also click the checkmark beside the answer to accept it and signal to others that your question has been answered. Remember that Stack Overflow is intended as a knoweldge base of useful questions and answers, not a general help desk. Please see https://stackoverflow.com/help/someone-answers – glennsl Feb 12 '18 at 16:41