OCaml模式匹配中的变量隐藏

问题描述

我有一个方法可以返回列表(特别是char值列表)中最常见元素的计数

这是我的代码

let getMostFrequentCharCount li =
    let hashTable = Hashtbl.create (List.length li)
    in
    let rec getMostFrequentCharCount li acc =
        match li with
            [] -> acc
            | head::tail ->
                (match (Hashtbl.find hashTable head) with
                    exception Not_found -> Hashtbl.add hashTable head 1
                    | _ -> let currentFreq = Hashtbl.find hashTable head 
                           in
                           Hashtbl.replace hashTable head (currentFreq+1));
                let currentFreq = Hashtbl.find hashTable head
                in
                if currentFreq > acc
                then
                    getMostFrequentCharCount tail currentFreq
                else
                    getMostFrequentCharCount tail acc
    in
    getMostFrequentCharCount li 0;;

由于某种原因,当我删除第二个模式匹配块(以match (Hashtbl.find hashTable head) with开头)的括号时,编译器抱怨我的累加器acc在下一个if语句{{ 1}},而if currentFreq > acc的类型应为acc

为什么括号会解决错误

解决方法

在OCaml语法中,match分支(在->之后)包含由;分隔的表达式的序列。因此,如果没有括号,则会将以下行作为match的{​​{1}}分支的一部分进行解析。

由于_返回unit,因此该匹配的第一个分支的类型为unit。这意味着Hashtbl.add分支也必须是unit类型。如果没有括号,则以下行会导致类型错误,因为它们不是unit类型。

我使用ocamlformat格式化带括号和不带括号的外部_

这是带括号的格式化代码:

match

以下是带括号的格式化代码:

match li with
| [] -> acc
| head :: tail ->
    ( match Hashtbl.find hashTable head with
    | exception Not_found -> Hashtbl.add hashTable head 1
    | _ ->
        let currentFreq = Hashtbl.find hashTable head in
        Hashtbl.replace hashTable head (currentFreq + 1) );
    let currentFreq = Hashtbl.find hashTable head in
    if currentFreq > acc then getMostFrequentCharCount tail currentFreq
    else getMostFrequentCharCount tail acc

我认为这很好地说明了问题。