Skip to content

Instantly share code, notes, and snippets.

@ianrussellsoftwarepark
Last active March 7, 2024 10:46
Show Gist options
  • Save ianrussellsoftwarepark/63e01137659bca179ad9f670901143b0 to your computer and use it in GitHub Desktop.
Save ianrussellsoftwarepark/63e01137659bca179ad9f670901143b0 to your computer and use it in GitHub Desktop.
Result composition from F# Essentials Lectures Session 5
type Customer = {
Id : int
IsVip : bool
Credit : decimal
}
type GetPurchasesError =
| HasOddId of int
type IncreaseCreditIfVipError =
| IsNotVip
type UpgradeCustomerError =
| GetPurchases of GetPurchasesError
| IncreaseCredit of IncreaseCreditIfVipError
// Customer -> Result<(Customer * decimal),GetPurchasesError>
let getPurchases (customer:Customer) : Result<(Customer * decimal),GetPurchasesError> =
if customer.Id % 2 = 0 then Ok (customer, 120M)
else Error (HasOddId customer.Id)
// Customer * decimal -> Customer
let tryPromoteToVip purchases =
let customer, amount = purchases
if amount > 100M then { customer with IsVip = true }
else customer
// Customer -> Result<Customer,IncreaseCreditIfVipError>
let increaseCreditIfVip (customer:Customer) : Result<Customer,IncreaseCreditIfVipError> =
if customer.IsVip then Ok { customer with Credit = customer.Credit + 100m }
else Error IsNotVip
// let upgradeCustomer (customer:Customer) : Result<Customer,UpgradeCustomerError> =
// customer
// |> getPurchases
// |> Result.mapError (fun err -> GetPurchases err)
// |> Result.map tryPromoteToVip
// |> fun result ->
// match result with
// | Ok cust ->
// match increaseCreditIfVip cust with
// | Ok res -> Ok res
// | Error err -> Error (IncreaseCredit err)
// | Error err -> Error err
// let upgradeCustomer customer : Result<Customer,UpgradeCustomerError> =
// customer
// |> getPurchases
// |> Result.mapError GetPurchases
// |> Result.map tryPromoteToVip
// |> Result.bind (fun cust ->
// match increaseCreditIfVip cust with
// | Ok res -> Ok res
// | Error ex -> ex |> IncreaseCredit |> Error
let mapError f result =
match result with
| Ok res -> Ok res
| Error ex -> ex |> f |> Error
// let upgradeCustomer customer : Result<Customer,UpgradeCustomerError> =
// customer
// |> getPurchases
// |> Result.mapError GetPurchases
// |> Result.map tryPromoteToVip
// |> Result.bind (fun cust ->
// increaseCreditIfVip cust
// |> Result.mapError (fun ex -> IncreaseCredit ex))
// let upgradeCustomer customer : Result<Customer,UpgradeCustomerError> =
// customer
// |> getPurchases
// |> Result.mapError GetPurchases
// |> Result.map tryPromoteToVip
// |> Result.bind (fun cust ->
// cust
// |> increaseCreditIfVip
// |> Result.mapError IncreaseCredit)
// let upgradeCustomer customer : Result<Customer,UpgradeCustomerError> =
// customer
// |> getPurchases
// |> Result.mapError GetPurchases
// |> Result.map tryPromoteToVip
// |> Result.bind (fun cust -> increaseCreditIfVip cust |> Result.mapError IncreaseCredit)
let upgradeCustomer customer : Result<Customer,UpgradeCustomerError> =
customer
|> getPurchases
|> Result.mapError GetPurchases
|> Result.map tryPromoteToVip
|> Result.bind (increaseCreditIfVip >> Result.mapError IncreaseCredit)
// Result.map : ('a -> 'b) -> Result<'a, 'c> -> Result<'b, 'c>
// Result.bind : ('a -> Result<'b, 'c>) -> Result<'a, 'c> -> Result<'b, 'c>
// Result.mapError : ('a -> 'b) -> Result<'c, 'a> -> Result<'c, 'b>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment