0

我正在尝试扩展James Hugard 的文章How do I plot a data series in F#? 当使用可变数量的函数参数时,我遇到了一个小故障。如果我像本例中那样专门为 Hugard 的 LineChartForm 命名函数,则代码在加载到 F# Interactive Interpreter 时按预期工作:

(* This code is based off of a Stack Overflow post by 
   James Hugard @ 
   https://stackoverflow.com/questions/3276357/how-do-i-plot-a-data-series-in-f
   *) 
module HuggardPlot

#r "System.Windows.Forms.DataVisualization" 
open System.Windows.Forms
open System.Windows.Forms.DataVisualization.Charting 

type LineChartForm( title, minX, maxX, func1, func2) =
   inherit Form( Text=title )

   let chart = new Chart(Dock=DockStyle.Fill)
   let area = new ChartArea(Name="Area1")

   (* Add the first plot Hugard style *) 
   let series = new Series()
   do series.ChartType <- SeriesChartType.Line
   do for i in minX .. maxX do 
      series.Points.AddXY(i, func1(i)) |> ignore   
   do series.ChartArea <- "Area1"
   do chart.Series.Add( series )

   (* Add the second plot Hugard style *) 
   let series2 = new Series()
   do series2.ChartType <- SeriesChartType.Line
   do for i in minX .. maxX do 
      series2.Points.AddXY(i, func2(i)) |> ignore   
   do series2.ChartArea <- "Area1"
   do chart.Series.Add( series2 )

   (* Add area1 to the plot *) 
   do chart.ChartAreas.Add(area)
   do base.Controls.Add( chart ) 

(* Convenience method to make it easier to plot functions *) 
let plotTwoFunctions minX maxX f1 f2 = 
   let LCF = new LineChartForm("lines", minX, maxX, f1, f2); 
   LCF.Show();

另一方面,如果我尝试使用http://msdn.microsoft.com/en-us/library/dd233213.aspx的参数数组部分中的技术通过 ParamArray 传递可变数量的函数,如下所示代码:

(* This code is based off of a Stack Overflow post by 
   James Hugard @ 
   https://stackoverflow.com/questions/3276357/how-do-i-plot-a-data-series-in-f
   *) 
module HuggardPlot

#r "System.Windows.Forms.DataVisualization" 
open System
open System.Windows.Forms
open System.Windows.Forms.DataVisualization.Charting 

type LineChartForm(
                    title, 
                    minX, 
                    maxX, 
                    [<ParamArray>] funcs: Object[]) =
   inherit Form( Text=title )

   let chart = new Chart(Dock=DockStyle.Fill)
   let area = new ChartArea(Name="Area1")

   do for func in funcs do 
      (* Add the first plot Hugard style *) 
      let series = new Series()
      do series.ChartType <- SeriesChartType.Line
      do for i in minX .. maxX do 
         series.Points.AddXY(i, func(i)) |> ignore   
      do series.ChartArea <- "Area1"
      do chart.Series.Add( series )      

   (* Add area1 to the plot *) 
   do chart.ChartAreas.Add(area)
   do base.Controls.Add( chart ) 

(* Convenience method to make it easier to plot functions *) 
let plotTwoFunctions minX maxX f1 f2 = 
   let LCF = new LineChartForm("lines", minX, maxX, f1, f2); 
   LCF.Show();

我在第 27 行收到一条错误消息,
series.Points.AddXY(i, func(i)) |> ignore
指出“此值不是函数,无法应用”,“func”下带有红色波浪线。

我怀疑这与我将[<ParamArray>] funcs: Object[]其用作 Hugard 先生的 LineChartForm 类型的参数定义这一事实有关。

我应该更改什么[<ParamArray>] funcs: Object[],以便第二个代码示例的第 27 行将“func”识别为函数?

4

1 回答 1

2

如果要创建一个采用params函数数组的方法,则需要将参数定义为[<ParamArray>] funcs: (float -> float)[]. 在您的原始版本中,类型Object[]意味着数组的各个元素是对象 - 如果您将元素的类型更改为函数,那么 F# 将识别出您可以调用它们。

但是,如果您只是对绘制 F# 数据的图表感兴趣,那么已经有一个很好的 WinForms DataVisualization 库包装器,称为F# Chart,可在 GitHub 上找到。MSDN 上还有一个全面的文档可用(如果您使用最新版本的库,FSharpChart则已重命名为 just Chart)。

要创建一个在指定范围内比较两个函数的图,您可以简单地编写:

let plotTwoFunctions minX maxX f1 f2 = 
  Chart.Combine
    [ Chart.Line [ for x in minX .. maxX -> x, f1 x ]
      Chart.Line [ for x in minX .. maxX -> x, f2 x ] ]

这将创建两个单独的折线图(使用两个函数生成的数据),然后使用Chart.Combine.

于 2013-05-28T03:03:02.713 回答