Getting Type Mismatch Errors, new to F#, how do I fix?

55 Views Asked by At

We are learning F# for one of my classes and using Visual Studio Code for it. I am doing a Homework Assignment and am getting the Type Mismatch Error for some of my functions. It is the only error but I don't know how to fix it. Any and all input or advice is appreciated, I am still learning so sorry if this is an easy fix. It is two series of code, but both have the same type of problem.

The Error Messages

Code 1

// Create a record type: Customer
type Customer = { Id: int; IsVip: bool; Credit: decimal }

// Real instances of customers
let customerVIP = { Id = 1; IsVip = true; Credit = 0.0M }
let customerSTD = { Id = 2; IsVip = false; Credit = 100.0M }

// Function 1: getPurchases
let getPurchases (customer: Customer) =
    if customer.Id % 2 = 0 then 120.0M
    else 80.0M

// Function 2: tryPromoteToVip
let tryPromoteToVip (purchase: decimal) (customer: Customer) =
    if purchase > 100.0M then { customer with IsVip = true }
    else customer

// Function 3: increaseCreditIfVip
let increaseCreditIfVip (customer: Customer) =
    if customer.IsVip then { customer with Credit = customer.Credit + 100.0M }
    else { customer with Credit = customer.Credit + 50.0M }

// Procedural
let upgradeCustomerProcedural customer =
    let purchases = getPurchases customer
    let updatedCustomer = tryPromoteToVip purchases customer
    increaseCreditIfVip updatedCustomer

// Nested
let upgradeCustomerNested customer =
    increaseCreditIfVip (tryPromoteToVip (getPurchases customer) customer)

// Composition operator
let upgradeCustomerComposed = getPurchases >> tryPromoteToVip >> increaseCreditIfVip

// Forward pipe operator
let upgradeCustomerPiped customer =
    customer
    |> getPurchases
    |> tryPromoteToVip customer
    |> increaseCreditIfVip

// Testing code
let assertVIP = upgradeCustomerComposed customerVIP = { Id = 1; IsVip = true; Credit = 100.0M }
let assertSTDtoVIP = upgradeCustomerComposed customerSTD = { Id = 2; IsVip = true; Credit = 200.0M }
let assertSTD = upgradeCustomerComposed { customerSTD with Id = 3; Credit = 50.0M } = { Id = 3; IsVip = false; Credit = 100.0M }

Code 2

open System

let cards = [1; 2; 3; 4; 5]

// Define the drawCard function
let drawCard deck =
    match deck with
    | card::restOfDeck -> (restOfDeck, card)
    | [] -> ([], -1) // Assuming -1 indicates an empty deck

[<EntryPoint>]
let main argv =

    let result =
        cards
        |> drawCard
        |> drawCard
        |> drawCard
        |> drawCard

    printfn "%A" result

    0

// Create an empty hand list
let hand = []

// Modify the drawCard function to accept a tuple of deck and hand
let drawCard (deck, hand) =
    match deck with
    | card::restOfDeck -> (restOfDeck, card::hand)
    | [] -> ([], hand)

[<EntryPoint>]
let main argv =

    let d, h =
        (cards, hand)
        |> drawCard
        |> drawCard

    printfn "Deck: %A Hand: %A" d h

    0
1

There are 1 best solutions below

0
Brian Berns On

Code 1:

getPurchases >> tryPromoteToVip >> increaseCreditIfVip

The problem here is that getPurchases produces a purchase amount, but tryPromoteToVip expects two inputs: a purchase amount and a customer. As a result, the composed function getPurchases >> tryPromoteToVip expects two separate customers as input (Customer -> Customer -> Customer). I don't think that's what you want.

Code 2:

        cards
        |> drawCard
        |> drawCard

The problem here is similar: drawCard takes a deck as input and produces a tuple as output. That means that you can't send the result of drawCard directly into another call to drawCard.


In both cases, it looks like you have some context that you want to pass through the pipeline (a Customer, a deck of Cards). There are elegant ways to do this in F#, but they are probably too advanced for a beginner. For now, I suggest that each function in a pipeline should take a single value as input, and return a single value as output, to make it easier to compose them. If you really need to pass more than one value at a time, you can tuple them (like in drawCard), but then modify the next function to expect the same type of tuple as input.

Related Questions in F#