Есть ли способ выразить мысль о том, что фрейм данных уже проверен? Лучший способ, который я могу придумать, - это создать тип оболочки для ограничения доступа. Я приветствую любые предложения.
Простой пример:
#r "nuget: Deedle"
open Deedle
type CustomFrame =
| Some of Frame<int,string>
| None
let map mapping option = match option with None -> None | Some x -> Some (mapping x)
let iter action option = match option with None -> () | Some x -> action x
let parse (df:Frame<_,_>) =
let keys = df.ColumnKeys |> Set.ofSeq
if keys.Contains("Entry") && keys.Contains("Color") then
df
|> Frame.indexRowsInt "Entry"
|> CustomFrame.Some
else
CustomFrame.None
let go (df:CustomFrame) =
df
|> map (Frame.filterRowsBy "Color" "Red")
let data = "Entry;Color;N\n1;Red;7\n2;Blue;42\n3;Blue;21"
let bytes = System.Text.Encoding.UTF8.GetBytes data
let stream = new MemoryStream( bytes )
Frame.ReadCsv(stream = stream,separators = ";",hasHeaders = true)
|> parse
|> go
|> iter (fun d-> d.Print())
Color N
1 -> Red 7
Пример был упрощен. Часто у меня есть список функций, в которых я работаю со столбцами, созданными ранее в другой функции, например aggregate |> pivot |> calculateMin1 |> calculateMin2 |> select
. Если я использую Option для всех из них, я не увижу ошибку, если я ошибусь в порядке.
Используйте Result
тогда?
Предположим, я создаю столбец min1
в calculateMin1
и использую его в calculateMin2
. Если все мои функции возвращают Ok frame
, а я возвращаю aggregate |> pivot |> calculateMin2 |> calculateMin1 |> select
. Он компилируется, и у меня есть проблема в моем производственном коде. Вы согласны?
Два предложения:
parse
возвращает стандартное значение Option
, как предлагает Федор.parse
возвращает None
, вообще не вызывайте go
и iter
.Если вы действительно хотите программировать с защитой после parse
, и дальнейшая проверка не требуется, вам больше не нужно значение None
. Таким образом, вы можете использовать упрощенный тип оболочки, чтобы всегда иметь проверенный кадр:
type ValidFrame = Valid of Frame<int,string>
let map f (Valid df) = f df |> Valid
let iter (f : _ -> unit) (Valid df) = f df
let go = map (Frame.filterRowsBy "Color" "Red")
А затем используйте его следующим образом:
Frame.ReadCsv(stream = stream,separators = ";",hasHeaders = true)
|> parse
|> Option.map (
Valid
>> go
>> iter (fun df -> df.Print()))
Однако лично я считаю тип оболочки излишним, если для этого нет веской причины.
Короткое замыкание звучит интересно. Благодарю вас! Мне очень нравится тот факт, что Deedle обеспечивает некоторую простую в использовании безопасность индексов строк, и мне просто интересно, могу ли я иметь то же самое для имен столбцов. Типы оберток кажутся немного излишними, я согласен.
Почему пользовательский клон
option
?