如何正确使用F#的Result.bind 解决类型不匹配编译错误
问题根源分析
- 你对
Result.bind的逻辑理解本身没有问题,它的作用就是接收一个Result<'T, 'E>类型值和一个'T -> Result<'U, 'E>类型的映射函数,返回Result<'U, 'E>类型值,完全适配你预期的调用场景。报错的核心原因是val1、val2的实际返回类型和你以为的不一致:
你定义的ifFalseThenError使用了function关键字,相当于这个函数有3个入参:第一个是返回成功时要包装的x、第二个是错误信息errorMessage、第三个是隐式的待匹配布尔值,完整签名为'T -> string -> bool -> Result<'T, string>。你在val1、val2中调用该函数时,只传入了前两个参数,没有传入布尔参数,导致返回结果是bool -> Result<float[], string>类型的函数,而非你预期的Result<float[], string>类型值。 - 导致该问题的直接原因是你多写了一层多余的匿名函数:F#的管道运算符
|>会自动把左侧的值作为右侧函数的最后一个参数传入,你额外包裹的fun x -> ...没有把布尔值传入ifFalseThenError,反而返回了只完成部分参数绑定的函数。
修复方案
直接去掉val1、val2末尾多余的匿名函数即可,同时注意处理Result的分支匹配,和函数返回类型标注对齐:
let ifFalseThenError x errorMessage = function | true -> Ok x | false -> Error errorMessage let val1 (initialeSandssynligheder : float[]) = initialeSandssynligheder |> Seq.sum |> (fun x -> x < 2) // 管道自动将左侧布尔值作为第三个参数传入,直接返回Result类型 |> ifFalseThenError initialeSandssynligheder "Some error" let val2 initialeSandssynligheder = initialeSandssynligheder |> Array.exists ((<) 0.0) // 同理去掉多余的匿名函数 |> ifFalseThenError initialeSandssynligheder "SomeOtherError" let beregnAlleOvergangssandsynligheder (initialeSandssynligheder: float[]) : float[] = let initialeSandssynligheder = [|1.0;1.0;1.0;1.0;1.0|] let initssh = initialeSandssynligheder |> val1 |> Result.bind val2 // 处理Result的两种分支,和返回类型标注对齐 match initssh with | Ok arr -> arr | Error err -> failwith err // 可根据业务需求替换为返回默认数组等逻辑
内容的提问来源于stack exchange,提问作者Viktor Jeppesen
相关产品推荐
相关产品推荐

