F#类型提供程序和数据处理

Tri*_*tan 9 f# type-providers

在上一个问题(使用静态类型语言中的异构数据)中,我询问了F#如何处理数据分析中的标准任务,例如操作无类型的CSV文件.动态语言擅长于基本任务

data = load('income.csv')
data.log_income = log(income)
Run Code Online (Sandbox Code Playgroud)

在F#中,最优雅的方法似乎是问号(?)运算符.不幸的是,在这个过程中我们失去了静态类型,仍然需要在这里和那里进行类型注释.

F#最令人兴奋的未来特征之一是类型提供商.在类型安全性损失最小的情况下,CSV类型提供程序可以通过动态检查文件来提供类型.

但数据分析通常并不止于此.我们经常通过一系列操作来转换数据并创建新的数据集.我的问题是,如果我们主要操纵数据,类型提供商可以提供帮助吗?例如:

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

这可以工作,但会污染全局命名空间.考虑添加列而不是创建新变量通常更为自然.有办法吗?

let data.logIncome = log(data.income) // won't work, sadly.
Run Code Online (Sandbox Code Playgroud)

当目标是创建新的派生数据集或清理数据集时,类型提供程序是否可以避免使用(?)运算符?

也许是这样的:

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

其他想法?

Chr*_*ith 6

简短的回答是否定的,答案很长(但你不喜欢结果).要记住的关键是F#是一种静态类型的语言,完全停止.

对于您提供的代码,newData具有哪些类型?如果它无法在编译时固定下来,那么你需要求助于从Obj进行转换.

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

想象一下colBind具有以下特征:

val colBind: Thingey<'a> -> 'b -> Thingey2<'a, 'b>
Run Code Online (Sandbox Code Playgroud)

这实际上适用于某种方式,但它不会普遍适用.因为最终你需要一个在编译时不存在的类型.

F#类型提供程序允许您静态键入源自标准编译时环境之外的数据.但是,类型仍然是静态的.没有办法在运行时动态地改变这些类型*.

*您可以使用诸如DynamicObject之类的恶作剧在运行时修改对象 .但是,一旦你开始沿着这条道路前进,你将失去静态类型语言的所有好处,例如Intellisense.(这是首先使用F#的主要原因.)

从概念上讲,你想要做的就是直截了当.该System.Data.DataTable类型已经存储的表格数据与动态地添加列的能力的概念.但由于在编译时不知道添加列的类型信息,因此必须将存储在这些列中的内容视为Obj并在运行时进行转换.