Search code examples
c#wpff#deedle

Designing an F# module to be called by C# (Console/MVC/WPF)


I have been trying to use Deedle F# Library to write an F# batch program. It has worked perfectly. However, I am not sure about the best design for the following 2 tasks:

  1. Combine the F# module into a existing ASP.net MVC/Web Api system

  2. Create a WPF interface to serve as a control panel and visual dependency controller for the various F# modules.

The type of tasks the F# modules are doing are processing time series and applying statistical processes to derive new time series.

I have been trying to create a class wrapper for the existing module so it can be called from C# code. I read from the C# Deep Dive that this is a better way to expose F# modules to C# callers.

The following is a sample wrapper:

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

The following is a sample module where most of the logic should reside:

 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

I have been trying to use NUnit to serve as a C# caller. I found myself putting most of the logic in the class do/let binding. The member methods are serving as passing the results to the caller. I don't think my approach is correct.

Can someone point me to the right direction? (I attempted to learn the F# WPF Framework on GitHub, but I am not yet up to the task)

I am aware Deedle is also avalable for C#. But, I really want to use F#. The sample code actually has too many side effects.


Solution

  • To put it bluntly, you want to build as little of your UI and framework in F# as possible. As you have noted, F# is a great language when it's great; otherwise, it is not recommended for application building (some hardcore functional-language-fanboys might fight me on that, but I stand by it, haha).

    I would recommend putting all of your unit-of-work F# code in a Portable F# Library (https://msdn.microsoft.com/en-us/library/hh913781.aspx). Then, referencing that library and calling methods from it is as simple as calling the classes and methods as you would from C# or VB classes and methods.

    There are also some templates that you can use (http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx).