我有一个名为Candle
的C#对象的列表(它是股市数据),我需要将这些对象中的一些平均为一个。
这些对象非常简单,它们仅包含一个字段浮点字段(Bid
,Ask
,Bidvolume
,Askvolume
)
我写了这段代码,但是我不明白为什么它不能编译:
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)
根本没有帮助。
答案 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
,因为我假设您的Ask
和Bid
值是浮点型的。如果它们是整数,请删除该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" )
因为它将被理解为:
( 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#类型系统非常受限制,因此我们必须将整数显式转换为浮点数。