【发布时间】:2016-12-25 15:18:19
【问题描述】:
type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let add<'a> (x: 'a) (y: 'a) (in_: Interpreter<'a>): 'a =
match in_ with
| RegularInterpreter r ->
x+y |> r
| StringInterpreter r ->
sprintf "(%s + %s)" x y |> r
在编译时无法解析 'a 的错误消息对我来说非常清楚。我猜测是否可以使上述工作的问题的答案是否定的,没有直接将函数添加到数据类型中。但是我还不如使用接口,或者完全摆脱泛型参数。
编辑:马克的回复确实符合我的要求,但让我扩展这个问题,因为我没有充分解释它。我想要做的是用上面的技术来模仿post 中所做的事情。这样做的动机是避免内联函数,因为它们的可组合性很差 - 如果没有专门的泛型参数,它们就不能作为 lambdas 传递。
我希望我可以通过将带有泛型参数的联合类型传递给闭包来解决它,但是...
type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let val_ x in_ =
match in_ with
| RegularInterpreter r -> r x
| StringInterpreter r -> r (string x)
let inline add x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ + y in_ |> r
| StringInterpreter r ->
sprintf "(%A + %A)" (x in_) (y in_) |> r
let inline mult x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ * y in_ |> r
| StringInterpreter r ->
sprintf "(%A * %A)" (x in_) (y in_) |> r
let inline r2 in_ = add (val_ 1) (val_ 3) in_
r2 (RegularInterpreter id)
r2 (StringInterpreter id) // Type error.
最后一行给出了类型错误。有没有解决的办法?尽管由于它们对可组合性的限制,我更希望函数不要被内联。
【问题讨论】:
-
我假设您出于某种原因探索并拒绝了方法重载和活动模式,但很想知道原因。可组合性?类型推断?
-
老实说,我现在真正需要的是 GADT,以便以类型安全的方式为我的库编写操作,而您在这里看到的只是获得所需多态性的失败尝试。我可以只用函数来完成它,我并不真的需要多态性……除非我可能需要它,而且我害怕提交,因为它会使库的结构过于僵化。另一方面,使用联合类型,由于模式匹配和简单的上下文相关执行,我将能够进行前瞻,但我将在 F# 中使用一种动态 DSL。
-
没有隐含的多态性,那些
inline函数真的有点像 C 函数,因为它们只是位于顶部并且你可以调用它们,但是你不能在没有风险的情况下在 lambdas 中传递它们类型错误。在图书馆的过去迭代中,我也很愚蠢地使用了它们,并被它所吸引。我想我会尝试以动态方式对接子弹并使用 DU - 没有通用参数。 -
另外,我认为不需要多说,但 DU 与函数具有双重性,因为它们只是省略了返回类型的函数,所以这就是多态性发挥作用的地方跟他们。我似乎每时每刻都有艰难的选择。