Question

Dans une question précédente ( travail avec des données hétérogènes dans une langue statiquement typé), je leur ai demandé comment les tâches standard poignées F # dans l'analyse de données, telles que la manipulation d'un fichier CSV typées. langauges dynamiques excellent dans les tâches de base comme

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

En F #, l'approche la plus élégante semble être l'opérateur point d'interrogation (?). Malheureusement, dans le processus, nous perdons typage statique et il vous faut toujours taper les annotations ici et là.

L'un des plus caractéristique de l'avenir passionnant de F # sont Fournisseurs de type . Avec une perte minimale de sécurité de type, un fournisseur de type CSV pourrait fournir des types en examinant dynamiquement le fichier.

Mais l'analyse des données ne généralement arrête pas là. Nous transformons souvent les données et créer de nouveaux ensembles de données, via un pipeline d'opérations. Ma question est, peut aider les fournisseurs type si nous manipulons la plupart des données? Par exemple:

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

Cela fonctionne, mais pollue l'espace de noms global. Il est souvent plus naturel de penser à ajouter une colonne, plutôt que de créer une nouvelle variable. Est-il possible de le faire?

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

Les fournisseurs de types fournissent une échappatoire à l'aide de la (?) Lorsque vous l'objectif est de créer de nouveaux jeux de données dérivés ou assainis?

Peut-être quelque chose comme:

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

D'autres idées?

Était-ce utile?

La solution

La réponse courte est non, la longue réponse est oui (mais vous ne voulez pas le résultat). L'essentiel à retenir est que F # est un langage statiquement typé, arrêt complet .

Pour le code que vous avez fourni, quel type ne newData-il? Si elle ne peut pas être coincé à la compilation, vous devez recourir à la coulée vers / à partir Obj.

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

Imaginez colBind a le sinature suivant:

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

Cela fait travailler pour une façon, mais cela ne fonctionnerait pas universellement. Parce que finalement vous auriez besoin d'un type qui n'existerait au moment de la compilation.

F # fournisseurs de type vous permettent de type statiquement données provenant de l'extérieur de l'environnement de compilation standard. Cependant, les types sont toujours statiques. Il n'y a aucun moyen de modifier ces types dynamiquement lors de l'exécution *.

  

* lors de l'exécution en utilisant manigances Vous pouvez modifier l'objet tel que    DynamicObject . Cependant, une fois que vous   commencer à aller dans cette voie, vous perdez   tous les avantages d'un tapés statiquement   tels que la langue IntelliSense. (Ce qui est une des principales raisons pour l'utilisation de F # en premier lieu.)

Conceptuellement, ce que vous voulez faire est simple. Le type System.Data.DataTable a déjà la notion de stockage des données tabulaires avec la possibilité d'ajouter dynamiquement des colonnes. Mais puisque les informations de type pour les colonnes ajoutées n'est pas connue au moment de la compilation, il en résulte que les choses stockées dans ces colonnes doivent être traitées comme Obj et casted lors de l'exécution.

Autres conseils

Sinon, vous pouvez créer « de » et « à » tables avec, avec des tableaux ayant les colonnes nécessaires. De cette façon, vous avez un schéma de requête et le résultat statiquement typé que les fournisseurs de type travaillent avec.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top