隐藏在OCaml'中的变量;s模式匹配

隐藏在OCaml'中的变量;s模式匹配,ocaml,Ocaml,我有一个方法,返回列表中最常见元素的计数(特别是一个char值列表) 这是我的密码: 让getMostFrequentCharCount li= 让hashTable=Hashtbl.create(List.length li) 在里面 让rec获取MOSTFREQUENTCHARCOUNT li acc= 与李相配 []->acc |头:尾-> (将(Hashtbl.find哈希表头)与 未找到异常->Hashtbl.add哈希表头1 |->让currentFreq=Hashtbl.find哈

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

这是我的密码:

让getMostFrequentCharCount li=
让hashTable=Hashtbl.create(List.length li)
在里面
让rec获取MOSTFREQUENTCHARCOUNT li acc=
与李相配
[]->acc
|头:尾->
(将(Hashtbl.find哈希表头)与
未找到异常->Hashtbl.add哈希表头1
|->让currentFreq=Hashtbl.find哈希表头
在里面
替换哈希表头(currentFreq+1);
让currentFreq=Hashtbl.find哈希表头
在里面
如果currentFreq>acc
然后
getMostFrequentCharCount尾部电流频率
其他的
getMostFrequentCharCount尾部附件
在里面
getMostFrequentCharCount li 0;;
出于某种原因,当我删除第二个模式匹配块(以
匹配(Hashtbl.find hashTable head)开头,并以
开头)周围的括号时,我的编译器抱怨我的累加器
acc
在下一个if语句
if currentFreq>acc
中有类型单位,而
acc
应该有类型
int


为什么括号会修复此错误?

在OCaml语法中,
匹配
分支(在
->
之后)包含一个由
分隔的表达式序列。因此,在没有括号的情况下,以下行将被解析为
\uu
match
分支的一部分

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

我使用ocamlformat格式化外部
匹配
,包括括号和不包括括号

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

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
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 )
以下是不带括号的格式化代码:

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
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 )

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

在OCaml语法中,
匹配
分支(在
->
之后)包含一个由
分隔的表达式序列。因此,在没有括号的情况下,以下行将被解析为
\uu
match
分支的一部分

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

我使用ocamlformat格式化外部
匹配
,包括括号和不包括括号

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

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
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 )
以下是不带括号的格式化代码:

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
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 )

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

谢谢你的解释;这很有帮助!我现在想知道,当IF语句<代码>如果CurrutFrq> ACC不是对应的<代码>匹配< /COD>分支>的返回语句时,为什么代码> ACC < /代码>被假定为类型单元?
匹配的所有分支(当然)必须具有相同的类型。因此,
acc
必须具有嵌套的
匹配类型。嵌套的
匹配的第一个分支显然具有类型单位。因此,
acc
必须具有类型单位。由于它与
currentFreq>acc
中的
currentFreq
相比较,因此它还必须具有int类型。这是一个类型错误。分析首先决定了
acc
的单元类型,因此这就是消息的措辞。但是如果
匹配
分支被定义为一个由
分隔的一个或多个表达式组成的序列(在
->
之后),并且所述序列必须返回与
匹配
块中所有其他分支相同的类型,为什么
acc
(在该if语句表达式中)被视为返回值(对于匹配
的分支
)当返回值为
getMostFrequentCharCount tail currentFreq
getMostFrequentCharCount tail acc
时,它需要是unit类型。下面的注释中不可能有复杂的讨论。如果你愿意的话,我可以补充更多。但要快速回答:分析必须按一定顺序进行。有三种类型需要相同:
acc
Hashtbl.add
,以及您提到的表达式。可以通过假设前两种类型相同来进行分析。也就是说,它可以通过假设
acc
为单元类型来启动。如果代码输入正确,顺序就无关紧要了。如果不是,你可以根据分析的顺序得到不同的错误。哦,等等,我想我明白了。如果没有括号,则与未找到异常对应的
匹配
分支返回一个单位类型,因此编译器假定外部
匹配
分支(对应于
[]
)也返回一个单位类型,该单位类型存储在变量
acc
中。因此,现在编译器假定
acc
此时是一个单元类型,当
acc
不是int类型时,如果
acc
在if语句中,编译器就会感到困惑。这就是你的意思吗?谢谢你的解释;这很有帮助!我现在想知道,当IF语句<代码>如果CurrutFrq> ACC不是对应的<代码>匹配< /COD>分支>的返回语句时,为什么代码> ACC < /代码>被假定为类型单元?
匹配的所有分支(当然)必须具有相同的类型。因此,acc必须