Sum of a predefined List F#

Viewed 125

I am a beginner F# learner, currently trying some Lists actions within a BlackJack F# implementation.

I am trying to sum the elements of a list which I created as follows:

let cardsvalue (k: Cards): List<int> =
    match k with
    |Ace ->  [1;11]
    |Two -> [2] 
    |Three -> [3]
    |Four -> [4]
    |Five -> [5]
    |Six -> [6]
    |Seven -> [7]
    |Eight -> [8]
    |Nine -> [9]
    |Ten | Jack | Queen | King -> [10] 

type Cards is just a union of the cards Two to Nine , Ten to King and Ace.

So I need some kind of recursive function CardPoints which simply adds items from cardsvalue for example [Two; Three] = [5] or [Ace; Ace; Ace] = [3; 13; 23; 33] meaning all possible values of the Ace. I have tried several common ways of getting the sum but I always end up with type mismatch or not supporting operator error. For example

let rec CardPoints (cp: List<Cards>): List<int> =   
   match cp with
   | head :: tail -> head + CardPoints tail
   | [] -> 0 

which is not accepting the + opperator.

I would love to see a possible implementation of this problem. Thank you for your time!

2 Answers

I am a beginner F# learner

Your code shows a nice systematic approach and you've already done most of the work to allow the type system (and intellisense) to help solve your problem.

let cardsvalue (k: Cards): List<int> =

A useful function with exactly the right type signature. Notice that it's greyed out. That means you are not using it.

let rec CardPoints (cp: List<Cards>): List<int> =

Also exactly right. You are giving as much help to the type system as possible which makes it almost certain that it will spot the exact point at which something is going wrong.

I always end up with type mismatch or not supporting operator error. For example

    | head :: tail -> head + CardPoints tail

Try using a binding to help figure this out:

    | head :: tail ->
        let tailPoints = CardPoints tail
        head + tailPoints

You can tell (by hovering over them) that head is a Cards and tailPoints is a List<int>. So you are trying to add a Cards to a List<int> and there is no such addition operation defined.

So you've honed this down to a smaller task: given a card (head: Cards), and given the points possible (tailPoints: List<int>) from the remaining cards, how can you find the points possible from all cards, which should be a List<int>? You will need to use your currently unused function cardsvalue and another small step and you are there.

Ok, your answer is very close. but you are trying to add a "Card" to a list of ints. what you want to do is take each possible value of the card and add that to each possible value of the sum of the rest of the cards.

OK, I probably wouldn't do it it quite like this, but maybe this is the easiest answer to understand (assuming you understand list comprehensions).

Its also no quite perfect functionally, but I'll leave that to you to find out and fix.

let rec cardPoints (cp: List<Card>): List<int> =   
   match cp with
   | head :: tail -> 
        [ for val1 in cardsvalue head do
            for val2 in cardPoints tail do 
                val1 + val2 ]
   | [] -> [0]
Related