2010-12-21 7 views
9

En una pregunta anterior (Working with heterogenous data in a statically typed language), pregunté cómo F # maneja las tareas estándar en el análisis de datos, como la manipulación de un archivo CSV sin tipo. langauges dinámicas sobresalen en tareas básicas comoF # Tipo de proveedores y procesamiento de datos

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

En F #, el enfoque más elegante parece ser el signo de interrogación (?) del operador. Desafortunadamente, en el proceso, perdemos tipeo estático y aún necesitamos anotaciones de tipo aquí y allá.

Una de las características futuras más interesantes de F # es Type Providers. Con una mínima pérdida de seguridad de tipo, un proveedor de tipo CSV podría proporcionar tipos mediante el examen dinámico del archivo.

Pero el análisis de datos generalmente no se detiene allí. A menudo transformamos los datos y creamos nuevos conjuntos de datos, a través de una cartera de operaciones. Mi pregunta es, ¿pueden los proveedores de tipo ayudar si la mayoría manipulamos datos? Por ejemplo:

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

Esto funciona pero contamina el espacio de nombres global. A menudo es más natural pensar en agregar una columna, en lugar de crear una nueva variable. ¿Hay alguna manera de hacerlo?

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

Do tipo proveedores proporcionan un escape de usar el (?) Del operador cuando el objetivo es la creación de nuevos conjuntos de datos derivado o limpiados en marcha?

Tal vez algo como:

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

Otras ideas?

Respuesta

6

La respuesta corta es no, la respuesta larga es sí (pero no le gustaría el resultado). La clave para recordar es que F # es un lenguaje estáticamente tipado, punto final.

Para el código que proporcionó, ¿qué tipo tiene newData? Si no se puede anclar en tiempo de compilación, entonces necesita recurrir a la conversión a/desde Obj.

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

Imagínese colBind tiene la siguiente sinature:

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

Eso sería realmente trabajar por un largo camino, pero no quiere trabajar de forma universal. Porque eventualmente necesitarías un tipo que no existiría en el momento de la compilación.

Los proveedores de tipo F # le permiten datos de tipo estático originados fuera del entorno estándar de tiempo de compilación. Sin embargo, los tipos siguen siendo estáticos. No hay forma de alterar esos tipos dinámicamente en tiempo de ejecución *.

* Es posible modificar el objeto en tiempo de ejecución utilizando travesuras como DynamicObject. Sin embargo, una vez que comience a recorrer esa ruta, perderá todos los beneficios de un lenguaje estáticamente tipado como Intellisense. (Que es una razón importante para usar F # en primer lugar.)

Conceptualmente, lo que quiere hacer es sencillo.El tipo System.Data.DataTable ya tiene la noción de almacenar datos tabulares con la capacidad de agregar columnas dinámicamente. Pero dado que la información de tipo para las columnas añadidas no se conoce en tiempo de compilación, se deduce que las cosas almacenadas en esas columnas deben tratarse como Obj y emitirse en tiempo de ejecución.

0

De forma alternativa, puede crear tablas 'de' y 'para' con, con las tablas to que tienen las columnas necesarias. De esta forma, tiene un esquema de resultados y consultas estáticamente tipados con los que trabajan los proveedores de tipos.

Cuestiones relacionadas