平均f#中的c#对象列表,我的语法出了什么问题

时间:2019-06-12 23:31:30

标签: f#

我有一个名为Candle的C#对象的列表(它是股市数据),我需要将这些对象中的一些平均为一个。

这些对象非常简单,它们仅包含一个字段浮点字段(BidAskBidvolumeAskvolume

我写了这段代码,但是我不明白为什么它不能编译:

            let zero = new Candle()
            let avg =   entries
                        |> List.fold (fun acc elem ->
                                (
                                    Ask = acc.Ask + elem.Ask,
                                    Bid = acc.Bid + elem.Bid,
                                    AskVolume = acc.AskVolume + elem.AskVolume,
                                    BidVolume = acc.BidVolume + elem.BidVolume
                                )
                            ) zero
                        |>
                            (
                                TimeStamp = time,
                                Ask = Ask / entries.Count,
                                Bid = Bid / entries.Count,
                                AskVolume = AskVolume / entries.Count,
                                BidVolume = BidVolume / entries.count,
                                Integrity = entries.Count / expectedCount
                            )

我收到以下错误:

  BooksCandle.fs(154, 41): [FS0039] The value or constructor 'Ask' is not defined.
  BooksCandle.fs(154, 51): [FS0039] The field, constructor or member 'Ask' is not defined.
  BooksCandle.fs(155, 41): [FS0039] The value or constructor 'Bid' is not defined. Maybe you want one of the following:   id
  BooksCandle.fs(155, 51): [FS0039] The field, constructor or member 'Bid' is not defined.
  BooksCandle.fs(156, 41): [FS0039] The value or constructor 'AskVolume' is not defined.
  BooksCandle.fs(156, 57): [FS0039] The field, constructor or member 'AskVolume' is not defined.
  BooksCandle.fs(157, 41): [FS0039] The value or constructor 'BidVolume' is not defined.
  BooksCandle.fs(157, 57): [FS0039] The field, constructor or member 'BidVolume' is not defined.
  BooksCandle.fs(159, 35): [FS0001] This expression was expected to have type    'bool * bool * bool * bool'    but here has type    'Candle'
  BooksCandle.fs(162, 37): [FS0001] This expression was expected to have type    'bool * bool * bool * bool -> 'a'    but here has type    ''b * 'c * 'd * 'e * 'f * 'g'
  BooksCandle.fs(170, 22): [FS0039] The value or constructor 'A' is not defined.

因此,我想我要操纵的对象不会被视为Candle,但是使用fun (acc : Candle) (elem : Candle)根本没有帮助。

3 个答案:

答案 0 :(得分:3)

您正在使用()定界符来查找记录,但记录使用{}定界符。将您的第一个管道更改为:

(fun acc elem ->
            {
                Ask = acc.Ask + elem.Ask,
                Bid = acc.Bid + elem.Bid,
                AskVolume = acc.AskVolume + elem.AskVolume,
                BidVolume = acc.BidVolume + elem.BidVolume
            }
)

然后也按照切斯特·赫斯基的答案中的建议更改第二个管道。

编辑:不,请稍等。您有let zero = new Candle()行这一事实使我重新考虑。前面您说过Candle是一个C#对象。然后,在这种情况下,您实际上想做的就是对新创建的zero对象的字段进行突变。在这种情况下,您需要<-运算符。 F#故意区分=<-运算符。 =表示等于,并且在let x = 5中使用,因为x 的值不能更改,并且始终相等由于未标记x mutable,因此该代码块其余部分中的5到5。 (如果x是一个对象,则该对象可能会改变其内部结构,但名称x将始终引用该对象)。另一方面,<-运算符用于分配。 =运算符看起来与不同,因为您不保证该值将永远存在。

因此,话虽如此,您实际需要的是将累加器功能更改为如下所示:

(fun acc elem ->
    acc.Ask <- acc.Ask + elem.Ask,
    acc.Bid <- acc.Bid + elem.Bid,
    acc.AskVolume <- acc.AskVolume + elem.AskVolume,
    acc.BidVolume <- acc.BidVolume + elem.BidVolume
    acc
)

请注意,我如何在最后一行上单独写出acc。 F#函数中的最后一个表达式是它的返回值。不需要return关键字。

然后您的第二个管道需要管道连接到一个函数中:

|> (fun result ->
        result.TimeStamp <- time,
        result.Ask <- result.Ask / float entries.Count,
        result.Bid <- result.Bid / float entries.Count,
        result.AskVolume <- result.AskVolume / float entries.Count,
        result.BidVolume <- result.BidVolume / float entries.count,
        result.Integrity <- entries.Count / expectedCount
)

请注意我如何将entries.Count转换为float,因为我假设您的AskBid值是浮点型的。如果它们是整数,请删除该float转换,但请注意,在对整数进行除法时,F#使用 integer 除法。 5 / 2的值为2,而不是2.5。如果您想使用2.5,则必须除以浮点数5.0 / 2.0

答案 1 :(得分:2)

在这里刺伤,但是我想猜你弃牌后管道中的第154行吗?如果是这样,那么问题就出在语法上:不是

|> (.... 

您需要将折叠的结果传递给函数:

|> fun reduced -> { TimeStamp = time
                    Ask = reduced.Ask/entries.Count
                    .... }

使用管道中引入的简化元素的属性。

答案 2 :(得分:2)

在F#中,对象和记录是不同的东西。您可以这样创建一个记录值:

{ Foo = "apple"; Bar = "banana" }

但是您不能使用类似的语法来创建对象。以下代码无法编译:

( Foo = "apple", Bar = "banana" )

因为它将被理解为:

  • 由2个组成部分组成的元组,因为它的形式为( component1, component2 )
  • 每个组件都是一个布尔值,因为存在一个比较=
  • Foo应该是名称Foo的值,但是这里没有这样的东西。与Bar类似。

相反,您必须编写:new MyClass ( Foo = "apple", Bar = "banana" )

我想按如下方式重写您的代码:

let zero = new Candle ()
let sum =
    entries
    |> List.fold
        (fun acc elem ->
            new Candle (
                Ask = acc.Ask + elem.Ask,
                Bid = acc.Bid + elem.Bid,
                AskVolume = acc.AskVolume + elem.AskVolume,
                BidVolume = acc.BidVolume + elem.BidVolume
            )
        )
        zero
let avg = new Candle (
    TimeStamp = time,
    Ask = sum.Ask / float entries.Length,
    Bid = sum.Bid / float entries.Length,
    AskVolume = sum.AskVolume / float entries.Length,
    BidVolume = sum.BidVolume / float entries.Length,
    Integrity = float entries.Length / float expectedCount
)

请注意,F#类型系统非常受限制,因此我们必须将整数显式转换为浮点数。