F#忽略模式匹配中的模式

时间:2020-07-23 05:36:42

标签: functional-programming f# pattern-matching

我可能会以错误的方式思考,但是我想忽略Some以外的任何情况。这是我正在使用| _ -> ignore的一些示例代码,但这似乎是错误的。有没有更好或更惯用的方式来做到这一点?我正在将一些OOP C#代码转换为F#,可能会出错。

match solarSystem.MinerCoords |> Map.tryFind minerId with
| Some currentMinerCoords ->
    match solarSystem.Minables |> Map.tryFind currentMinerCoords with
    | Some _ ->
        do! GetMinerActor(minerId).StopMining() |> Async.AwaitTask
    | _ -> ignore
| _ -> ignore

2 个答案:

答案 0 :(得分:5)

您似乎在async返回的Async<unit>计算表达式中。因此,您应将ignore替换为return ()(其中()是单位值),以便所有分支都返回相同的类型:

match solarSystem.MinerCoords |> Map.tryFind minerId with
| Some currentMinerCoords ->
    match solarSystem.Minables |> Map.tryFind currentMinerCoords with
    | Some _ ->
        do! GetMinerActor(minerId).StopMining() |> Async.AwaitTask
    | _ -> return ()
| _ -> return ()

编辑:显示整个异步块以及之后如何继续运行更多代码的简化版本:

async {
    match Some 1 with
    | Some a ->
        printfn "Maybe do this"
        do! Async.Sleep 500
    | _ -> ()

    printfn "Always do this"
    do! Async.Sleep 500
    printfn "Finished" }

答案 1 :(得分:1)

您可以使每个分支产生一个异步,然后才可以执行它。像这样:

let dummyAsync = async { return () }
let theAsync =
    match solarSystem.MinerCoords |> Map.tryFind minerId with
    | Some currentMinerCoords when solarSystem.Minables |> Map.tryFind currentMinerCoords |> Option.isSome ->
        GetMinerActor(minerId).StopMining() |> Async.AwaitTask
    | _ ->
        dummyAsync
do! theAsync

请注意,使用when关键字可删除一个不必要的分支。

习惯上来说,当您以嵌套方式匹配多个选项值时,则应使用函数Option.bind和/或Option.map

let dummyAsync = async { return () }
let theAsync =
    solarSystem.MinerCoords
    |> Map.tryFind minerId
    |> Option.bind (fun currentMinerCoords -> solarSystem.Minables |> Map.tryFind currentMinerCoords)
    |> Option.map (fun _ -> GetMinerActor(minerId).StopMining() |> Async.AwaitTask)
    |> Option.defaultValue dummyAsync
do! theAsync