I have a function that takes input and either succeeds, or returns part of the input, or returns None. I will give an example of a list of phone numbers that are dialed until someone answers one of the numbers, and then the remaining numbers should be skipped. And at the end there is a logging of a successful number or error message.
My first decision, which I find too complicated, and on the first attempt, uses the sowing state of failure, which seems inelegant:
type PhoneNumber = int let tryCallNumber phoneNumber = if phoneNumber % 2 = 0 then Some phoneNumber else None let nextCall phoneNumberOption nextNumber = match phoneNumberOption with | Some num -> phoneNumberOption | None -> tryCallNumber nextNumber let logCall phoneNumberOption = match phoneNumberOption with | Some num -> printfn "%i" num | None -> printfn "%s" "failed" let phoneNumbers = [111; 222; 444; 555] do List.fold (fun state num -> (nextCall state num)) None phoneNumbers |> logCall
I pulled it over with the best List function, tryPick:
type PhoneNumber = int let tryCallNumber phoneNumber = if phoneNumber % 2 = 0 then Some phoneNumber else None let logCall phoneNumberOption = match phoneNumberOption with | Some num -> printfn "%i" num | None -> printfn "%s" "failed" let phoneNumbers = [111; 222; 444; 555] do List.tryPick (fun num -> tryCallNumber num) phoneNumbers |> logCall
Does this sound like a good approach? After reading about monadic error handling, I wonder if I should do something like that.
source share