1

I need a recursive function in F# that gives me the biggest value of a non empty list. example:

biggest [2;4;5;3;9;3] 

should return 9

Update 1

I'm learning recursive functions and this is an exercise from the book with no answer on it. I thought it was ok to ask here but it seems it was not a good idea. Ok, I didn't write any code example so that it seemed to be a homework exercise of a lazy guy. Anyway this is my best try:

let rec highest l = 
    match l with 
    |[] -> 0 
    |x::y::xs -> if x > y then highest x::xs
                 else highest y::xs 

But this doesn't work. I cannot use F# functions, this is for learning purpose of course. So sorry if made you loose some time and thanks for your help.

Seb
  • 69
  • 7
  • If this is homework, please indicate so in the question. Otherwise the people who answer don't have the right context. – Fyodor Soikin Nov 01 '16 at 14:45
  • 4
    Why should it be recursive? List.max does what you want. – hvester Nov 01 '16 at 14:49
  • 3
    @hvester probably because that's the homework assignment. – N_A Nov 01 '16 at 14:50
  • @MarkSeemann I'm learning recursive functions in F# and tried many things, I guess this is the best `let rec highest l =` `match l with` `[] -> 0` `|x::y::xs -> if x>y then highest x::xs` `else highest y::xs` But doesn't work – Seb Nov 01 '16 at 16:26
  • @FyodorSoikin it's an exercise from the book to learn recursion, but has no solution, thanks for the tip – Seb Nov 01 '16 at 16:34
  • @mydogisbox it's just an exercise, not really homework, thanks – Seb Nov 01 '16 at 16:37
  • The update makes this a much better question. The next step in making it even better is replacing "But this doesn't work." with details on exactly how it doesn't work. – N_A Nov 01 '16 at 18:05

2 Answers2

3

Before the answer: this question is weird and Stackoverflow is probably not the best place for it.

  • If it's for production code, use List.max. (Puns aside, recursion isn't its own reward...)
  • If it's for homework, try to understand recursion instead of delegating your exercises to random people on the internet.
  • If it's a puzzle/code golf, this is the wrong site and it could be clearer what the requirements are.

Anyway, this can be answered as posted, with the following requirements:

  • The solution is tail-recursive, not just recursive. Obviously I don't want to write a function to replace List.max just to needlessly grow the stack.
  • The function biggest that is called in the question's code is directly the recursive one and gets no additional arguments. If I take the question literally, this seems to be a requirement, so I'm not allowed to use an accumulator.

List.max is implemented with a mutating loop and therefore doesn't qualify (link goes to F# source code). So this needs a custom implementation:

let rec biggest = function
    | h1 :: h2 :: t -> biggest ((max h1 h2) :: t)
    | [result] -> result
    | [] -> failwith "list empty"

It's a pretty weird solution, but it does what's asked for and works for long lists.

Vandroiy
  • 6,163
  • 1
  • 19
  • 28
  • 1
    Why didn't you use an inner function with an accumulator to fullfill the "signature requirement" without having to "be weird" ? – Sehnsucht Nov 01 '16 at 16:15
  • @Vandroiy Your code is what was looking for, I was close to your answer but something was wrong in my code. I'm just learning recursion, don't want to bother people on the internet, my excuses if I did it with you. Thank you very much – Seb Nov 01 '16 at 16:59
  • 1
    @Sehnsucht that might be cheating. The function called in the question should be recursive, not a function that's being called by it. The requirement of being recursive is arbitrary anyway, so the stricter rule might just as well be the correct one. So of course I use the strictest interpretation. :P – Vandroiy Nov 01 '16 at 17:36
  • 2
    @Seb No worries, I don't feel bothered; I just want to be sure that my answers do more good than harm. Stackoverflow sometimes has questions that look like attempts to short-cut understanding and just get something to "work". Of course I don't know your intentions, I just want to suggest to focus on "why" questions and concepts rather than specific solutions. I wish you all the best with your learning! – Vandroiy Nov 01 '16 at 17:44
1

After some days thinking on it and with some help at school I came up with this, it's an alternative solution to Vandroiy's one:

let rec max_value l =
    match l with
    |[] -> []
    |[x] -> [x]
    |(x::y::xs) ->  if x<y then max_value (y::xs)
                    else max_value (x::xs)

thanks a lot

Seb
  • 69
  • 7