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.
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
Code 1:
The problem here is that
getPurchasesproduces a purchase amount, buttryPromoteToVipexpects two inputs: a purchase amount and a customer. As a result, the composed functiongetPurchases >> tryPromoteToVipexpects two separate customers as input (Customer -> Customer -> Customer). I don't think that's what you want.Code 2:
The problem here is similar:
drawCardtakes a deck as input and produces a tuple as output. That means that you can't send the result ofdrawCarddirectly into another call todrawCard.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.