Я пытаюсь использовать Deedle F # Library для написания пакетной программы F #. Он отлично работал. Однако я не уверен в лучшем дизайне для следующих двух задач:
-
Объедините модуль F # в существующую систему ASP.NET MVC/Web Api
-
Создайте WPF-интерфейс, чтобы служить в качестве панели управления и визуального контроллера зависимостей для различных модулей F #.
Тип задач, которые выполняются модулями F #, - это обработка временных рядов и применение статистических процессов для получения новых временных рядов.
Я пытаюсь создать оболочку класса для существующего модуля, чтобы его можно было вызвать из кода С#. Я прочитал из С# Deep Dive, что это лучший способ разоблачить модули 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 для вызова С#. Я обнаружил, что ставил большую часть логики в классе do/let binding
. Методы-члены служат для передачи результатов вызывающему. Я не думаю, что мой подход правильный.
Может ли кто-нибудь указать мне в правильном направлении? (Я попытался изучить F # WPF Framework на GitHub, но я еще не достиг этой задачи)
Я знаю, что Deedle также доступен для С#. Но я действительно хочу использовать F #. Пример кода имеет слишком много побочных эффектов.