【问题标题】:F# Result Unit Test Fails without type annotation - Can I avoid the type annotation in this case?F# 结果单元测试在没有类型注释的情况下失败 - 在这种情况下我可以避免类型注释吗?
【发布时间】:2020-02-09 04:13:42
【问题描述】:

我正在做一些 F# 练习,任务是实现一个名为 clean 的函数,该函数接受字符串输入并返回解析后的数字。

let clean input = 
    input
    |> Seq.filter Char.IsDigit
    |> Seq.fold (fun acc cur ->
                    if acc = "" && cur = '1' then
                        acc
                    else acc + string cur) ""
    |> uint64
    |> Ok

这是我的临时解决方案。但是下面的单元测试失败了:

[<Fact>]
let ``Cleans the number`` () =
    let expected: Result<uint64,string> = Ok 2234567890UL
    let parsed = clean "(223) 456-7890"
    parsed |> should equal expected

失败了:

FsUnit.Xunit+MatchException : 异常类型 'FsUnit.Xunit+MatchException' 被抛出。预期:等于确定 2234567890UL 实际:是 Microsoft.FSharp.Core.FSharpResult2[System.UInt64,System.Object]
at FsUnit.Xunit.Assert.That.Static[a](a actual, IMatcher
1 匹配器)
在PhoneNumberTest.Cleans 中带有dots() 的数字

所以我加了一个类型注解:let clean input: Result&lt;uint64,string&gt; // function body is the same

我可以避免类型注释吗?第一个解决方案失败的技术原因是什么?

【问题讨论】:

    标签: types f# annotations


    【解决方案1】:

    如果没有类型注释,您的clean 函数将被推断为具有泛型类型seq&lt;char&gt; -&gt; Result&lt;uint64,'a&gt;,因此在您需要类型注释的情况下。

    编译器推断泛型类型的原因是您总是返回Result&lt;'ok,'error&gt; 类型的OK 分支。

    正如您的函数名称所暗示的那样,Result 可能不是这里最合适的返回类型?

    【讨论】:

      【解决方案2】:

      这里的问题是编译器无法仅从成功值Ok 2234567890UL 推断出在失败情况下您的Result 将具有的类型。当它不知道时,它只使用obj,因此默认推断类型为Result&lt;uint64, obj&gt;。比较不同类型的对象总是false

      这有点不幸,因为您正在比较两个值,因此它们必须具有相同的类型。提供shouldequal 操作的FsUnit 库没有严格类型化,允许您比较不同类型的值。你可以写:

      1 |> should equal "1"
      

      有一个library FsUnitTyped 实现了 FsUnit 的类型化版本。我没有这方面的经验,但看起来你可以使用它并编写:

      [<Fact>]
      let ``Cleans the number`` () =
          let expected = Ok 2234567890UL
          let parsed = clean "(223) 456-7890"
          parsed |> shouldEqual expected
      

      这将解决您的问题 - 编译器可以推断出 expected 的类型必须与 parsed 的类型相同,因此它会自动使用正确的类型。

      【讨论】:

      • 谢谢你的解释。 1 |&gt; should equal "1" 单元测试不失败真的很奇怪
      猜你喜欢
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多