简体   繁体   English

对 F# 和 FsUnit 中的序列使用 `should equal`

[英]Using `should equal` with sequences in F# and FsUnit

I am using FsUnit.Xunit .我正在使用FsUnit.Xunit I am getting a failure for the following test case:以下测试用例失败:

[<Fact>]
let ``Initialization of DFF`` () =
    dff Seq.empty Seq.empty |> should equal (seq {Zero})

The test failure is:测试失败是:

  Message: 
FsUnit.Xunit+MatchException : Exception of type 'FsUnit.Xunit+MatchException' was thrown.
Expected: Equals seq [Zero]
Actual:   seq [Zero]

  Stack Trace: 
That.Static[a](a actual, IMatcher`1 matcher)
Signal.Initialization of DFF() line 11

I get the same error if the test is:如果测试是,我会得到同样的错误:

[<Fact>]
let ``Initialization of DFF`` () =
    dff Seq.empty Seq.empty |> should equal (Seq.singleton Zero)

I have never tested equality of sequences using FsUnit.Xunit , so I am confused what's going on.我从未使用FsUnit.Xunit测试过序列的相等性,所以我很困惑发生了什么。 I'm not even for sure what the failure message is telling me, as it seems to be saying that the expected and actual are the same.我什至不确定失败消息告诉我什么,因为它似乎在说预期和实际是相同的。 I can get this to work fine by converting the sequences to lists, but it would be nice to not have to do that.我可以通过将序列转换为列表来使其正常工作,但不必这样做会很好。

Could someone explain what's going on here?有人可以解释这里发生了什么吗? It seems I'm not understanding the error message and thus probably something about Equals and comparing sequence values (literals?).似乎我不理解错误消息,因此可能是关于Equals和比较序列值(文字?)。 Thanks.谢谢。


Source code to be able to reproduce (I think this is everything):能够重现的源代码(我认为这就是一切):

type Bit =
    | Zero
    | One

type Signal = seq<Bit>

let Nand a b =
    match a, b with
    | Zero, Zero -> One
    | Zero, One  -> One
    | One,  Zero -> One
    | One,  One  -> Zero

let Not input =
    Nand input input

let And a b =
    Not (Nand a b)

let Or a b =
    Nand (Not a) (Not b)

let private liftToSignal1 op (signal: Signal) : Signal =
    Seq.map op signal

let private liftToSignal2 op (signalA: Signal) (signalB: Signal) : Signal =
    Seq.map2 op signalA signalB

let Not' = liftToSignal1 Not

let And' = liftToSignal2 And

let Or' = liftToSignal2 Or

let rec dff data clock : Signal =
    seq {
        yield Zero
        yield! Or' (And' data clock)
                        (And' (dff data clock) (Not' clock))
    }

This is an issue with structural vs. referential equality.这是结构与引用平等的问题。 In F# seq { 'a' } = seq { 'a' } // false but [ 'a' ] = [ 'a' ] // true due to seq being IEnumerable and not supporting structural equality (or comparison).在 F# 中seq { 'a' } = seq { 'a' } // false but [ 'a' ] = [ 'a' ] // true因为seqIEnumerable并且不支持结构相等(或比较)。 Lists (and other F# container-like types) are much more 'intelligent', ie they support structural equality / comparison if the contained objects support it:列表(和其他 F# 容器类类型)更加“智能”,即如果包含的对象支持,它们支持结构相等/比较:

[ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] =
  [ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] // true

but don't, if they contain anything that doesn't: [ box(fun() -> 3) ] = [ box(fun() -> 3) ] // false但不要,如果它们包含任何不包含的内容: [ box(fun() -> 3) ] = [ box(fun() -> 3) ] // false

So, to make the test work, add a List.ofSeq :因此,为了使测试工作,添加一个List.ofSeq

dff Seq.empty Seq.empty |> List.ofSeq |> should equal [ Zero ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM