Cloud Spider
Cloud Spider

Reputation: 305

What is wrong in F# code?

In F# I am trying to get last element of give list. I wrote below code

let rec findLast t =
    match t with
        | hd :: [] -> hd
        | hd :: tl -> findLast tl
        | _ -> -1

printfn "%A" (findLast [1,2,3,4,5])

But when I tried to execute it in F# Interactive it complain as below

error FS0001: This expression was expected to have type int but here has type 'a * 'b * 'c * 'd * 'e

I just want to know what is wrong in above code. I know there are different smart and elegant ways to get last element from list in F#. But I am interested to know what is wrong in above code ?

Upvotes: 3

Views: 165

Answers (3)

Aaron Winston Comyn
Aaron Winston Comyn

Reputation: 97

As @Phillip-Scott-Givens pointed out, you've likely made a totally common (especially for C#'ers), error and used a comma to separate a list instead of a semi-colon.

This results in a tuple list [(1, 2, 3, 4, 5)] and not an integer list [1;2;3;4;5]. Getting unexpected asterisks in your type definitions is a symptom of this :)

That said, here a few different functions that get the last value from your tuple, list, and tuple list (ref: https://stackoverflow.com/a/1175123/5470873):

// Data: 
let tuples = [ (1,2,3,4,5); ]      // = [1,2,3,4,5]
let firstListElement = tuples.[0]  


// Access: 
let rec lastItemInList = function
    | hd :: [] -> hd
    | hd :: tl -> lastItemInList tl
    | _ -> failwith "Empty list."
let lastValueOfFirstItem = function
    | (_, _, _, _, last) :: _ -> last
    | _ -> -1
let lastValueOfTuple = function _, _, _, _, last -> last
// same as: let lastValueOfTuple myTuple = 
//              match myTuple with
//              | (_, _, _, _, last) -> last


// Examples:
tuples |> lastItemInList              // val it : int * int * int * int * int = (1, 2, 3, 4, 5)
tuples |> lastValueOfFirstItem        // val it : int = 5
tuples |> List.map lastValueOfTuple   // val it : int list = [5]
firstListElement |> lastValueOfTuple  // val it : int = 5

Upvotes: 1

Phillip Scott Givens
Phillip Scott Givens

Reputation: 5464

1,2,3,4,5 is a tuple. 'a * 'b * 'c * 'd * 'e is a tuple definition. Create a list with semicolons [1;2;3;4;5]. [1,2,3,4,5] is a list of tuples with one item which is a quintuple.

let rec findLast t =
    match t with
        | hd :: [] -> hd
        | hd :: tl -> findLast tl
        | _ -> -1

printfn "%A" (findLast [1;2;3;4;5])

Upvotes: 2

Olaf
Olaf

Reputation: 3986

Try this one:

let rec lastElem = function
    | []    -> None
    | [x]   -> Some x
    | x::xs -> lastElem xs

You can try it in the REPL:

> lastElem [1;2;3];;

val it : int option = Some 3

> lastElem ["a";"b";"c"];;

val it : string option = Some "c"

Upvotes: 1

Related Questions