F# 匹配模式鉴别器未定义问题

F# match pattern discriminator not defined issue

我正在编写一个转置递归函数,但我遇到了一个问题。所以我想通过调用 isTable 函数来使用匹配进行检查,以验证输入 M 是否有效 table,但是它出错了,我不确定如何修复它

let isTable list =
    match List.map List.length list |> List.distinct |> List.length with
    | 1 -> true
    | _ -> false


let rec transpose M = 
    match M with 
    | []::_ -> []
    | (isTable M) -> [] // i want to check here if M is a valid table
    | _ ->  (List.map List.head M::transpose(List.map List.tail M))

错误 FS0039:未定义模式鉴别器 'isTable'。

试试

let rec transpose M = 
    match M with 
    | []::_ -> []
    | _ -> match (isTable M)  with
       | true - > [] // i want to check here if M is a valid table
       | _ ->  (List.map List.head M::transpose(List.map List.tail M))

作为编程风格的问题,我建议添加像 Table 这样的数据构造函数,以便您 可以 匹配它,但这应该能让事情正常进行。

活动模式是一种方法,但为单次使用添加一个模式的开销是不值得的。一个简单而整洁的解决方案是使用 when 子句:

let rec transpose M = 
    match M with 
    | []::_ -> []
    | _ when isTable M -> []
    | _ ->  (List.map List.head M::transpose(List.map List.tail M))

None 的答案显示了如何将您的案例变成 活动模式 。这对于 (1) 可读性和 (2) 代码的可重用性特别有用。假设您需要 isTable 不止一次,这可能是有益的。

/// Active pattern, must start with capital letter.
let (|IsTable|_|) list =
    match List.map List.length list |> List.distinct with
    | [_] -> Some list
    | _ -> None


let rec transpose M = 
    match M with 
    | []::_ -> []
    | IsTable M -> []    // using the active pattern
    | _ ->  
        List.map List.head M::transpose(List.map List.tail M)

顺便说一句,您的 isTable 函数匹配超过 List.length 结果。一个List.length遍历整个列表就是O(n)。由于我们只对结果是一项感兴趣,因此上述方法会更有效,从代码中至少删除一次迭代。