Поставщики типа F # и обработка данных - PullRequest
9 голосов
/ 22 декабря 2010

В предыдущем вопросе ( Работа с разнородными данными на статически типизированном языке ) я спросил о том, как F # обрабатывает стандартные задачи анализа данных, такие как манипулирование нетипизированным CSV-файлом.Динамические языки превосходно справляются с базовыми задачами, такими как

data = load('income.csv')
data.log_income = log(income)

. В F # наиболее элегантным подходом является оператор с вопросительным знаком (?).К сожалению, в этом процессе мы теряем статическую типизацию и все еще нуждаемся в аннотациях типов здесь и там.

Одной из самых интересных функций F # в будущем являются Поставщики типов .При минимальной потере безопасности типов поставщик типов CSV может предоставлять типы путем динамического изучения файла.

Но анализ данных, как правило, на этом не останавливается.Мы часто преобразуем данные и создаем новые наборы данных с помощью конвейера операций.Мой вопрос: могут ли провайдеры типов помочь, если мы в основном манипулируем данными?Например:

open CSV // Type provider
let data = CSV(file='income.csv') // Type provider magic (syntax?)
let log_income = log(data.income) // works!

Это работает, но загрязняет глобальное пространство имен.Часто более естественно думать о добавлении столбца, а не о создании новой переменной.Есть ли способ сделать это?

let data.logIncome = log(data.income) // won't work, sadly.

Предоставляют ли поставщики типов возможность избежать использования оператора (?), Когда целью является создание новых производных или очищенных наборов данных?

Возможно, что-то вроде:

let newdata = colBind data {logIncome = log(data.income)}  // ugly, does it work?

Другие идеи?

Ответы [ 2 ]

6 голосов
/ 01 января 2011

Короткий ответ - нет, длинный ответ - да (но вам не понравится результат).Главное, что нужно помнить, это то, что F # является языком статической типизации, точка останова .

Для предоставленного вами кода, какой тип имеет newData?Если это не может быть закреплено во время компиляции, тогда вам нужно прибегнуть к приведению к / от Obj.

// newdata MUST have a static type, even if obj
let newdata = colBind data {logIncome = log(data.income)}  

Представьте, что colBind имеет следующую синатуру:

val colBind: Thingey<'a> -> 'b -> Thingey2<'a, 'b>

Это будетна самом деле работают по-разному, но это не будет работать универсально.Потому что в конечном итоге вам понадобится тип, который не будет существовать во время компиляции.

Поставщики типа F # позволяют статически печатать данные, исходящие из-за пределов стандартной среды компиляции.Тем не менее, типы все еще статичны.Невозможно динамически изменять эти типы во время выполнения *.

* Вы можете изменить объект во время выполнения, используя такие махинации, как DynamicObject .Однако, как только вы начнете идти по этому пути, вы потеряете все преимущества статически типизированного языка, такого как Intellisense.(Что является основной причиной использования F # в первую очередь.)

Концептуально, то, что вы хотите сделать, это прямо вперед.Тип System.Data.DataTable уже имеет понятие хранения табличных данных с возможностью динамического добавления столбцов.Но поскольку информация о типе для добавленных столбцов не известна во время компиляции, из этого следует, что вещи, хранящиеся в этих столбцах, должны обрабатываться как Obj и приводиться во время выполнения.

0 голосов
/ 23 марта 2014

В качестве альтернативы, вы можете создать таблицы «из» и «в» с помощью таблиц с необходимыми столбцами.Таким образом, у вас есть статически типизированная схема запроса и результата, с которой работают поставщики типов.

...