【问题标题】:F# type error with one level of indentation, not with another一级缩进的 F# 类型错误,而不是另一级缩进
【发布时间】:2017-03-22 11:02:26
【问题描述】:

我正在浏览Hopac 文档,遇到了这个奇怪的类型错误:

let create x = Job.delay <| fun () ->
    let c = {reqCh = Ch (); replyCh = Ch ()}
    Job.iterateServer x <| fun x ->
        c.reqCh >>= function
          | Get -> c.replyCh *<- x >>-. x
          | Put x -> Job.result x
    >>-. c

Scrapers.SC.fsx(48,10): error FS0001: Type mismatch. Expecting a
    ''a'    
but given a
    'Cell<'a>'    
The types ''a' and 'Cell<'a>' cannot be unified.

c 是一个Cell&lt;'a&gt;。此代码与页面中的代码编译得很好:

let create x = Job.delay <| fun () ->
  let c = {reqCh = Ch (); replyCh = Ch ()}
  Job.iterateServer x <| fun x ->
        c.reqCh >>= function
          | Get -> c.replyCh *<- x >>-. x
          | Put x -> Job.result x
  >>-. c

这两者之间的唯一区别是第一个缩进的深度 - 2 而不是 4。

通常,当缩进出现问题时,我会收到“可能不正确的缩进”警告,而不是类型错误。所以它一定是真的糊涂了。

我用F#十年了,还是不懂缩进规则。

我错过了什么?

【问题讨论】:

标签: syntax f#


【解决方案1】:

&gt;&gt;-. 运算符有 4 个字符,因此您需要更多缩进才能使其不与上面的表达式连接。运营商的规则是为了做出类似的东西

    expr
 |> f1
 |> f2

使用管道中表达式左侧的运算符。

【讨论】:

  • 顺便说一句,您可以在语言规范中阅读有关此内容,这是“越位规则的例外”中的第一个
【解决方案2】:

除了“2 个空格或 4 个空格”之外,我在该代码中看到了另一个缩进差异,那就是 c.reqCh 的缩进。在第一个示例中,c.reqChiterateServer 对齐,而在第二个示例中,则不是。我自己并不完全理解缩进规则(因此我在前面的评论中链接到https://github.com/fsharp/fslang-suggestions/issues/470),但我怀疑c.reqChiterateServer 对齐的事实在某种程度上导致F# 解析器误解这是什么。 (不过我不知道如何)。

如果您采用第一个示例,并在 c.reqCh 行和接下来的两行前面添加一个空格,会发生什么情况?也就是说,如果你把它改成这样呢?

let create x = Job.delay <| fun () ->
    let c = {reqCh = Ch (); replyCh = Ch ()}
    Job.iterateServer x <| fun x ->
         c.reqCh >>= function
           | Get -> c.replyCh *<- x >>-. x
           | Put x -> Job.result x
    >>-. c

现在c.reqCh 已经缩进过去iterateServer 的开头,但其他一切都与 4 空格缩进示例相同,这是否会使错误消失?如果是这样,那么这就是两个示例之间的实际差异。 (虽然我仍然无法解释为什么需要缩进)。

我也想知道如果你将&lt;|iterateServer 中的用法改为使用括号会发生什么,例如:

let create x = Job.delay <| fun () ->
    let c = {reqCh = Ch (); replyCh = Ch ()}
    Job.iterateServer x (fun x ->
        c.reqCh >>= function
          | Get -> c.replyCh *<- x >>-. x
          | Put x -> Job.result x
    ) >>-. c

这也会使类型错误消失吗?如果是这样,那么我们还需要查看&lt;|的优先级来找出错误原因。

【讨论】:

  • 啊。 @Brian 的解释看起来是正确的。导致缩进问题的是&gt;&gt;-. 运算符,而不是iterateServer。因此,我的最后一个示例(带括号)也应该有效,因为右括号与 &gt;&gt;-. 在同一行,因此代码的哪一部分是 &gt;&gt;-. 运算符的左操作数是明确的。
猜你喜欢
  • 2017-08-12
  • 2010-12-15
  • 2018-02-08
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 2021-06-04
相关资源
最近更新 更多