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

9
在之前的问题中(使用静态类型语言处理异构数据),我询问了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
短答案是否定的,长答案是肯定的(但你可能不会喜欢结果)。需要记住的关键是,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)在运行时修改对象。但是,一旦您开始走这条路,就会失去使用 F# 的主要原因之一:静态类型语言的 IntelliSense(智能感知)。 ”
从概念上讲,您想要做的事情很简单。 System.Data.DataTable 类型已经具有存储表格数据并具有动态添加列的功能。但是,由于在编译时未知添加列的类型信息,因此存储在这些列中的内容必须被视为 Obj 并在运行时进行强制转换。

0

或者,您可以创建“从”和“到”表格,其中“到”表格具有所需的列。这样,您就拥有了一个类型静态查询和结果模式,供类型提供程序使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接