我如何限制非功能?

时间:2016-02-17 16:22:05

标签: f#

我正在研究抽象出System.Data.IDbConnection及其兄弟姐妹的代码。

目标代码

let inline runWithConnection connector f = 
        match connector with
        | ICon con -> f con
        | CString cs -> 
            use conn = new SqlConnection(cs)
            openConnection conn
            f conn

我可以看到类型约束编译和运行,但约束到对象并没有预期的效果。我想约束一个对象或值,这个对象或值不是需要更多输入来返回某些东西的函数。或者以这样的方式写这个:如果它确实返回一个函数,那么可能创建的连接不会被关闭直到f完成它。

let inline runWithConnection connector (f:_ -> 't when 't :> obj) = 
        match connector with
        | ICon con -> f con
        | CString cs -> 
            use conn = new SqlConnection(cs)
            openConnection conn
            f conn

It seems你可以说't : not struct,但你不能说't: not delegate

我考虑过做f.GetType(),但后来我不知道像.IsClass.IsAbstract.IsValue这样的类型属性是否与委托类型一致而不是其他简单类型。这也就是运行时而不是编译时间,并没有真正改善这种情况。

2 个答案:

答案 0 :(得分:3)

我认为你说的是​​,当你使用curry runWithConnection调用f时,这不起作用,因为在返回第一个部分函数后连接已被释放。

没有通用约束可以解决这个问题,因为你不能约束一个不是函数的类型。这与F#,C#,Java等相同。

你可能会抛出一个运行时异常,但我认为重新审视你正在尝试的模式要容易得多。我会通过让外部函数执行它传递的函数来询问你节省了什么,而不是仅仅将生成的连接作为IDisposable返回。这将使调用函数控制连接的范围,例如:

use conn = getConnection myConnector
doSomethingWithConnection conn anotherArg

答案 1 :(得分:2)

请注意,您的问题并不仅限于功能返回类型 - 有很多"正常"类型也有问题。考虑f是否为(fun conn -> [conn]) - 然后您只是返回一个列表,但该列表中存储的连接将在函数返回时关闭。同样,您可以创建一个类类型ConnectionUser,其构造函数接受并存储一个连接,其方法/属性使用它,并且由于同样的原因,它不能作为f的返回类型工作。所以我同意Tim Rogers你应该尝试提出一个更清晰的抽象。

顺便说一句,我不认为inline在这里给你买任何东西,所以你可以放心地放弃它。