我实际上遇到了F#编译器可能存在的奇怪问题。以下代码给出了一个错误,我无法理解原因:
yield Animal(
AnimalType(animal.AnimalType.Value),
error-->if Option.isSome animal.AnimalSubType then Some(AnimalSubType(animal.AnimalSubType.Value)) else None,
AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
)
编译器抱怨Animal应该接受3个参数但实际上只占用2.我猜它没有意识到if参数在行尾(在逗号中)结束。我可以通过在违规行周围添加()来运行代码:
yield Animal(
AnimalType(animal.AnimalType.Value),
--> OK (if Option.isSome animal.AnimalSubType then Some(AnimalSubType(animal.AnimalSubType.Value)) else None),
AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
)
但我想了解这个问题。为什么这会解决问题,例如,这不是?
yield Animal(
AnimalType(amimal.AnimalType.Value),
error-->if (Option.isSome animal.AnimalSubType) then (Some(AnimalSubType(animal.AnimalSubType.Value))) else (None),
AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
)
我没有抬头看过F#的语法,但我猜每次F#看到一个if
句子时,它会期望else
条款,可能会跟着通过else
条款。我猜,只要我对else
条款小心,一切都会好的。
这里有什么问题?
答案 0 :(得分:4)
编译器将错误行末尾的逗号解释为else
分支返回的元组的一部分,即
yield Animal(
a,
if c then Some(b) else None,
d
)
被解析为:
yield Animal(
a,
if c then Some(b) else ((None, ...? )
d
)
这就是为什么你的第一个修复工作而不是第二个,因为在第二个修复中添加括号只包含幻像元组的第一个元素,而不是元组本身,即:
yield Animal(
a,
if c then Some(b) else (None),
d
)
被解析为:
yield Animal(
a,
if c then Some(b) else ((None), ...? )
d
)
答案 1 :(得分:3)
问题与如何在F#中创建元组有关:
> let test (a,b,c) = "Test"
> test(1, if true then Some 1 else None,1);;
test(1, if true then Some 1 else None,1);;
-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error FS0001: Type mismatch. Expecting a
'a * 'b * 'c
but given a
'a * 'b
The tuples have differing lengths of 3 and 2
这清楚地表明编译器认为test
正在采用两个参数,但编译器认为这两个参数是什么?由于这种类型的函数实际上只是将单个参数作为元组的函数,我们可以解释这行代码:
> 1, if true then Some 1 else None,1;;
1, if true then Some 1 else None,1;;
----------------------------^^^^^^
stdin(19,29): error FS0001: This expression was expected to have type
int option
but here has type
'a * 'b
因此,您可以看到编译器将None,1
视为else
表达式的if
中的表达式,这就是编译器期望int option
的原因。为了防止这种情况,您需要向编译器指示if
表达式的起点和终点。实现这一目标的最简单方法是简单地将括号括在它周围:
> 1,(if true then Some 1 else None),1;;
val it : int * int option * int = (1, Some 1, 1)
现在我们得到了预期的元组。