我有一个接受输入的函数,并且成功并返回一些输入或返回None。我将举例说明拨打的电话号码列表,直到有人回复其中一个号码,然后应跳过其余的号码。最后会记录成功的号码或错误消息。
我认为我的第一个解决方案太复杂了,并且在第一次尝试时也使用了故障状态的播种,这似乎是不优雅的:
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
我用更好的List函数,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
这看起来像是一种好方法吗?在阅读了关于monadic错误处理的内容之后,我想知道我是否应该以某种方式在这种精神上做更多的事情。
答案 0 :(得分:3)
习得性很难衡量。我认为你的方法是最接近惯用的。你有Tomas'签名...我会为function
添加logCall
快捷方式,删除do
,管道phoneNumbers
,eta-reduce tryCallNumber
lambda:
let phoneNumbers = [111; 222; 444; 555]
let tryCallNumber phoneNumber =
if phoneNumber % 2 = 0 then Some phoneNumber
else None
let logCall = function
| Some num -> printfn "%i" num
| None -> printfn "failed"
phoneNumbers
|> List.tryPick tryCallNumber
|> logCall
个人(不幸的是,在.NET / F#standard-lib中非惯用),我还将tryCallNumber
重命名为callNumber
,作为IMO {{ 1}}返回类型足够明显,我的代码往往是option
- 很重,不依赖于异常。与try
类似 - 删除async
后缀的默认库。