Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# less than operator in pattern matching

For some reason the less than operator in this pattern match will not work. It's the only error I have and it's driving me insane. I'm probably missing something really obvious but all help is appreciated.

let CheckAccount account = 
match account with
| {Balance < 10.00} -> Console.WriteLine("Balance is Low")
| {Balance >= 10.00 and <= 100.00} -> Console.WriteLine("Balance is OK")
| {Balance > 100.00} -> Console.WriteLine("Balance is High")

This is the type:

type Account = {AccountNumber:string 
            mutable Balance:float} 
            member this.Withdraw(amnt:float) = 
                if amnt > this.Balance then
                    Console.WriteLine("Unable to withdraw. The Amount you wish to withdraw is greater than your current balance.")
                else
                    this.Balance <- this.Balance - amnt
                    Console.WriteLine("You have withdrawn £" + amnt.ToString() + ". Your balance is now: £" + this.Balance.ToString())
            member this.Deposit(amnt:float) =
                this.Balance <- this.Balance + amnt
                Console.WriteLine("£" + amnt.ToString() + " Deposited. Your new Balance is: £" + this.Balance.ToString())
            member this.Print = 
                Console.WriteLine("Account Number: " + this.AccountNumber)
                Console.WriteLine("Balance: £" + this.Balance.ToString())
like image 261
Jacob Avatar asked Dec 25 '22 19:12

Jacob


1 Answers

You can use pattern matching to extract the balance value, bind it to a new name and then compare the values using the when clause:

let CheckAccount account = 
  match account with
  | {Balance = b} when b < 10.00 -> Console.WriteLine("Balance is Low")
  | {Balance = b} when b >= 10.00 && b <= 100.00 -> Console.WriteLine("Balance is OK")
  | {Balance = b} when b > 100.00 -> Console.WriteLine("Balance is High")

I would say that in this case, you are not actually getting much from using pattern matching. If you wrote the same code using if, then it would probably look nicer.

You can use a bit fancier approach and define active patterns that let you compare values:

let (|LessThan|_|) k value = if value < k then Some() else None
let (|MoreThan|_|) k value = if value > k then Some() else None

Then you can use those instead:

let CheckAccount account = 
  match account with
  | {Balance = LessThan 10.0} -> Console.WriteLine("Balance is Low")
  | {Balance = LessThan 100.0 & MoreThan 10.0 } -> Console.WriteLine("Balance is OK")

This is actually fairly interesting - because you can use the & construct to combine multiple active patterns as in LessThan 100.0 & MoreThan 10.0.

like image 100
Tomas Petricek Avatar answered Jan 16 '23 14:01

Tomas Petricek