Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sum up a Member on a seq<type>?

Tags:

f#

Could someone help me afloat here? Still new to F#, actually trying to use it for the first time for something serious but got stuck on this nOOb issue.

I have a type Asset

type Asset(line:string) = 
    let fields = line.Split(',') 
    member this.EAD = Double.Parse(fields.[8])

Then i expose a csv file as a seq<Asset>:
'data' here is a seq<string> of the lines in the file

let assets = Seq.map(fun line -> Asset(line)) data

Now I want to get the total EAD of these assets, but I get an error

'This value is not a function and cannot be applied'.

Here's some of the things I tried:

let totEAD = Seq.sum(a.EAD) assets // first try
let totEAD = Seq.sum(fun(a)->a.EAD) assets // pretty sure this is a function..

let getEad(a:Asset) = a.EAD // val getEad : Asset -> float ... is it a val of a function?
let x = Seq.sum(fun (a) -> getEad(a)) assets // nope...

Thanks in advance,

Gert-Jan

update:

This works, but I'm still puzzled why I can't do this in one go, any tips there?

let x = Seq.map(fun (a:Asset) -> a.EAD) assets // first turn it into a seq<float>
let tot = Seq.sum(x)
like image 381
gjvdkamp Avatar asked Dec 04 '22 09:12

gjvdkamp


1 Answers

Your problem here is that Seq.sum assumes it is able to work on the whole type and does not accept a lambda. It is looking for a (+) operator to be defined on your type. What you want to do is use sumBy, which does accept a lambda.

Additionally, prefer the pipe-lining syntax. If you specify the input sequence first, the clever type inference system can then work out in the sumBy lambda what type you are dealing with automatically so you won't have to add type annotations:

let total =
    assets 
    |> Seq.sumBy( fun a -> a.EAD )
like image 97
Ross McKinlay Avatar answered Jan 06 '23 02:01

Ross McKinlay