【问题标题】:Is it possible in F# to factor out type constraints是否可以在 F# 中排除类型约束
【发布时间】:2020-02-12 09:59:37
【问题描述】:

我正在使用下面的代码

// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : ^a when ^a : (static member TryParse : string * ^a byref -> bool) = 
    let r = ref defaultVal
    if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents)) 
    then !r 
    else defaultVal  

但我注意到类型约束

^a : (static member TryParse : string * ^a byref -> bool

使用两次。有没有办法做到以下几点

constraint Parsable a = ( a : ^a : (static member TryParse : string * ^a byref -> bool)

并像使用 Parsable 一样

// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : Parsable = 
    let r = ref defaultVal
    if (^a : (Parsable) (text, &r.contents)) 
    then !r 
    else defaultVal  

【问题讨论】:

    标签: f# type-constraints


    【解决方案1】:

    正如现有答案所说,您不需要显式地在类型签名中重复约束,因为 F# 编译器可以推断它。进一步分解出涉及类型约束的代码的另一种方法是只使用调用TryParse 方法(并具有类型约束)的tryParse 函数,然后从tryParseWithDefault 调用此函数。

    这样,您可以将调用成员的“核心”逻辑与任何额外的逻辑分开。当你这样做时,你不再需要重复约束,因为编译器会推断它:

    let inline tryParse text = 
        let mutable r = Unchecked.defaultof<_>
        (^a : (static member TryParse: string * ^a byref -> bool) (text, &r)), r 
    
    let inline tryParseWithDefault (defaultVal:'a) text =
        match tryParse text with 
        | true, v -> v
        | _ -> defaultVal
    

    【讨论】:

    • 我想这是目前可以做到的最好的。遗憾的是,类型约束不能被分解并放入以后可以应用的命名组中。有点让我想起了 C++20 的概念。我为此添加了一个后续问题,该问题进一步开发了上述代码,但遇到了不同的问题。 stackoverflow.com/questions/58407301/…
    【解决方案2】:

    我不知道,但是,您可以通过让 F# 推断签名来简化函数:

    let inline tryParseWithDefault defaultVal text = 
        let r = ref defaultVal
        if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents)) 
        then !r 
        else defaultVal
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      相关资源
      最近更新 更多