Mkeefeus
Mkeefeus

Reputation: 25

Doubling elements of a list in f#

I am attempting to double the elements of a given list but am getting an error " This expression was expected to have type ''a list'
but here has type 'int' " when defining a new list

let list1 = [5;10;15;20;25;30]
let rec doubleListElements list =
    match list with
    |[]-> 0
    |head::tail ->
        let doubledList = [head*2::doubleListElements tail]
        0
let printList = doubleListElements list1
printfn "%A" printList

I am very new to f# and don't fully understand how things work, I am more used to an object oriented approach

Upvotes: 2

Views: 443

Answers (2)

user4649737
user4649737

Reputation:

You can make use of different kinds of data structures, such as sequences:

namespace FSharpBasics

module DoubleList =

    let private list1 = [ 5; 10; 15; 20; 25; 30 ]

    (*operations*)
    let doubleList (list: List<int>) =
        Seq.init list.Length (fun index -> list.[index] * 2)
            |> Seq.toList

    [<EntryPoint>]
    let main argv =
        doubleList list1 
            |> printf "%A"
        System.Console.ReadKey() |> ignore
        0

Upvotes: 0

Taylor Wood
Taylor Wood

Reputation: 16194

The function in your question will work with some changes:

let rec doubleListElements list =
  match list with
  | [] -> []
  | head::tail -> head*2::doubleListElements tail

First important thing to keep in mind is "what do I want to give to and receive from this function". In your case, your input is a int list and desired output is an int list. This means wherever your function returns a value it must be an int list. Your function has two places where a value is returned:

  | [] -> [] // return empty list
  | head::tail ->
      head*2::doubleListElements tail // return a list (but recurse)

In your original function your return values are always 0 which of course doesn't satisfy the int list return type.

|[]-> 0 // return value
|head::tail ->
    let doubledList = [head*2::doubleListElements tail]
    0   // return value

In this expression, a doubledList is created but that value is essentially discarded because it is unused and it's not the return value. The return value is the final value in the expression: 0. I think this is a very common mistake to see as people learn functional languages that are expression-based coming from imperative statement-based languages.

In this particular expression only the final value matters. In a statement-based language you might've mutated some program state before returning a value (which is also totally possible in F# but mutability is usually avoided).

let foo x =
  let y = x + x // the value of this expression is discarded: y is unused
  x * x         // the value of this expression is returned

The only other necessary change is to not wrap your returned list in another list in each recursion. head*2::doubleListElements tail is just a list. [head*2::doubleListElements tail] is the same list inside of another list because it's wrapped in square bracket list literals. After that change it works:

val printList : int list = [10; 20; 30; 40; 50; 60]

Upvotes: 3

Related Questions