我只是想从列表中检索头部,但我收到的错误表明The type 'Government' is not compatible with the type 'seq<government>'.
type Government = {
Id : Id;
Name : string;
Abbreviation : string;
ParentId : string option;
}
type GovernmentStructure<'gov> =
| Root of Government : 'gov * SubGov : GovernmentStructure<'gov> list
| Node of Government : 'gov * SubGov : GovernmentStructure<'gov> list
| Leaf of Government : 'gov
let rec findGovernment (gov : Government) (governmentStructure : GovernmentStructure<Government> list) =
[
for x in governmentStructure do
match x with
| Root(gov', subGov) ->
if gov = gov' then yield gov' else yield! findGovernment gov subGov
| Node(gov', subGov) ->
if gov = gov' then yield gov' else yield! findGovernment gov subGov
| Leaf(gov') ->
if gov = gov' then yield gov'
] |> List.head // This is where I get the error
答案 0 :(得分:3)
findGovernment
返回单个项目(从List.head
返回的项目),而不是集合。因此,您希望在递归调用时使用yield
,而不是yield!
:
let rec findGovernment (gov : Government)
(governmentStructure : GovernmentStructure<Government> list) =
[
for x in governmentStructure do
match x with
| Root(gov', subGov) ->
if gov = gov' then yield gov' else yield findGovernment gov subGov
| Node(gov', subGov) ->
if gov = gov' then yield gov' else yield findGovernment gov subGov
| Leaf(gov') ->
if gov = gov' then yield gov'
] |> List.head
答案 1 :(得分:3)
想一想:findGovernment
函数有哪些返回类型?
如果你查看整个陈述,那么人们会认为它是Government
- 因为你要回复调用List.head
的结果可能是Government list
。
但是,如果您查看列表定义,则会有一行yield! findGovernment ...
。由于yield!
指令期望参数为seq<_>
类型,因此findGovernment
必须返回一系列内容。
那么它毕竟是什么回归?一个Government
或其序列?编译器无法为您做出决定,所以它会抱怨。
我认为你的错误是过度工程
首先,我们只考虑一下问题:对于Root
和Node
个案例,结果是该节点匹配,否则结果位于SubGov
;对于Leaf
情况,如果匹配则结果是叶子
让我们写下来:
match x with
| Root(g, _) | Node(g, _) when g = gov -> g
| Root(_,sub) | Node(_, sub) -> findGovernment gov sub
| Leaf g when g = gov -> g
但是等等,现在我们立即在这个算法中看到一个漏洞:如果查找值根本不在结构中怎么办?该函数应该返回什么?实际上有两个选项:return Government option
,表示可能没有返回值,或者只是崩溃。让我们简单地让它崩溃,现在:
match x with
| Root(g, _) | Node(g, _) when g = gov -> g
| Root(_,sub) | Node(_, sub) -> findGovernment gov sub
| Leaf g when g = gov -> g
| _ -> failwith "Can't find it."
但是现在,仔细观察:每次你返回一些东西,你只是在将某些东西与gov
进行比较之后才这样做。换句话说,此函数可以返回的唯一值是等于gov
的值。所以问题是:为什么不返回gov
?
let findGovernment gov = gov
我知道,这看起来很愚蠢,但重点是:如果你把你的逻辑推向最终结论,而这个结论结果证明是愚蠢的,那就意味着逻辑开始有问题。