设计一个可被C#(控制台/MVC/WPF)调用的F#模块。

13

我一直在尝试使用Deedle F#库编写F#批处理程序。它运行得很完美。但是,我不确定以下2个任务的最佳设计:

  1. 将F#模块合并到现有的ASP.net MVC / Web Api系统中

  2. 创建一个WPF界面作为控制面板和不同F#模块的视觉依赖控制器。

F#模块正在处理时间序列,并应用统计过程以生成新的时间序列。

我一直在尝试为现有模块创建一个类包装器,以便可以从C#代码中调用它。我从C#深入学习路径中了解到,这是一种更好的方式来向C#调用方公开F#模块。

以下是示例包装器:

type TimeSeriesDataProcessor(fileName:string) = 
        let mutable _fileName = fileName
        let _rawInputData = loadCsvFile _fileName
        let _pivotedData = _rawInputData 
                       |> pivotRawData 
                       |> fillPivotedRawData
                       |> calculateExpandingZscore

    //read and write 
    member this.FileName
        with get () = _fileName
        and set (value) = _fileName <- value
    member this.RawInputData
        with get () = _rawInputData
    member this.PivotedData
        with get () = _pivotedData
    member this.rawInputDataCount
        with get () = _rawInputData.RowCount
    member this.pivotedDataCount
        with get () = _pivotedData.RowCount
下面是一个示例模块,其中大部分逻辑应该驻留:
 module Common = 

    let loadCsvFile (fileName:string ) : Frame<int,string> =
        let inputData = Frame.ReadCsv(fileName)
        inputData


    let pivotRawData inputData:Frame<DateTime,string> = 
        let pivotedData = inputData |> Frame.pivotTable (fun k r -> r.GetAs<DateTime>("Date"))  
                              (fun k r -> r.GetAs<string>("Indicator")) 
                              (fun f -> let maxVal = f?Value |> Stats.max 
                                        match maxVal with
                                        | Some mv -> mv
                                        | _ -> Double.NaN
                              )
        pivotedData

    let fillPivotedRawData inputData:Frame<DateTime,string> = 
        let filledA = inputData?A |> Series.fillMissing Direction.Forward
        inputData?A<-filledA
        let filledB = inputData?B |> Series.fillMissing Direction.Forward
        inputData?B<-filledB

        inputData

    let calculateExpandingZscore inputData:Frame<DateTime,string> = 
        let expandingMeanColA = inputData?A |> Stats.expandingMean
        let expandingMeanColB = inputData?B |> Stats.expandingMean
        let expandingStdevColA = inputData?A |> Stats.expandingStdDev
        let expandingStdevColB = inputData?B |> Stats.expandingStdDev
        let expandingZscoreColA = (inputData?A - expandingMeanColA)/expandingStdevColA
        let expandingZscoreColB = (inputData?B - expandingMeanColB)/expandingStdevColB
        inputData?ExpdingMeanA <- expandingMeanColA
        inputData?ExpdingMeanB <- expandingMeanColB
        inputData?ExpdingStdevA <- expandingStdevColA
        inputData?ExpdingStdevB <- expandingStdevColB
        inputData?ExpdingZscoreA <- expandingZscoreColA
        inputData?ExpdingZscoreB <- expandingZscoreColB
        inputData

我一直在尝试使用NUnit作为C#调用者。我发现自己将大部分逻辑放在了do / let binding类中。成员方法将结果传递给调用者。我认为我的方法不正确。

有人能指点我正确的方向吗?(我试图学习GitHub上的F# WPF Framework,但我还没有达到要求)

我知道Deedle也可用于C#。但是,我真的想使用F#。该示例代码实际上具有太多的副作用。


3
你应该查看这个链接:http://fsharp.org/specs/component-design-guidelines/ - N_A
你的实际问题是什么?从C#调用(使用F#编写的)CLR接口不是问题... - Robetto
1个回答

4
简单来说,您希望尽可能少地使用F#构建UI和框架。正如您所注意到的那样,F#是一种伟大的语言,但在某些情况下,不建议用于应用程序构建(一些强硬的函数式语言粉丝可能会反驳我,但我坚持这一观点,哈哈)。
我建议将所有的工作单元F#代码放入可移植的F#库中 (https://msdn.microsoft.com/en-us/library/hh913781.aspx)。然后,引用该库并从中调用方法就像从C#或VB类和方法中调用一样简单。
还有一些可以使用的模板 (http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接