我试图找出如何处理模式匹配的情况,根据匹配返回不同的类型,我知道它必须为每个分支返回相同的类型,所以我不知道什么是“正确的”处理方式这样的情况是:
我试着在下面举一个混乱的例子,paintArr是一个数组,代表一个可以包含某种颜色或空槽的托盘。
paintArr。[i,j] .color属于Color选项,包含黑色和白色。
每个插槽的模式匹配应决定颜色是黑色还是白色,并将其索引添加到适当的数组中。
let sort (paintArr: Pallete) =
let black = [||]
let white = [||]
for i = 0 to 5 do
for j = 0 to 5 do
match ((Option.get (paintArr.[i,j])).color) with
| White -> Array.append white paintArr.[i,j]
| Black -> Array.append black paintArr.[i,j]
| None -> "not sure what to do here"
(black, white)
基本上,我认为我的问题归结为:你如何处理这样的情况,在某些情况下我会得到一个匹配,要求我什么都不做,或者可能只是与其他情况有所不同?
答案 0 :(得分:7)
序言:很明显,你对F#缺乏经验。如果这是真的,我建议你先阅读某种书或一套教程(我总是推荐https://fsharpforfunandprofit.com/)。您正在尝试使用比完整初学者应该处理的代码更复杂的代码。
首先,请注意Array.append
没有"更改" ("更新","修改")数组,而是返回一个新数组 - 您给它的原始数组和新元素的串联。有了这些知识,很容易看出你的Array.append
电话是无用的:它们会返回一些东西,但你只是立即扔掉它。
从上下文中,我理解你实际想要做的是用它的扩展版本替换有问题的数组。为此,您需要声明数组mutable
,然后使用&#34;破坏性更新&#34; operator <-
:
black <- Array.append black paintArr.[i,j]
F#中的破坏性更新运算符<-
等同于C语言中的赋值语句=
。
现在,如果您使用这样的破坏性更新运算符,此类表达式的结果类型将为unit
- 一个空类型,用于表示&#34;没有值&#34;。这种类型只有一个值,它被写成两个括号,它们之间没有任何内容。例如:
> let x = ()
val x : unit = ()
所以要从所有分支机构实现&#34;相同的类型&#34;规则,您可以让第三个分支只返回unit
值,而不调用任何函数:
| None -> ()
将以上所有内容应用到您的代码中,我们得到了这个:
let sort (paintArr: Pallete) =
let mutable black = [||]
let mutable white = [||]
for i = 0 to 5 do
match ((Option.get (paintArr.[i,j])).color) with
| White -> white <- Array.append white paintArr.[i,j]
| Black -> black <- Array.append black paintArr.[i,j]
| None -> ()
(black, white)
但请注意,这仍然无法编译,因为其中还有其他错误。首先,Option.get
仅在paintArr.[i,j].color
为Some
值时有效,但在其None
时会崩溃。其次,即使此功能成功,它也会返回一种颜色,但是您会尝试将其与None
进行比较,而paintArr.[i,j].color
不是颜色。这将产生编译时错误。
此时有点难以推断出你真正想做的事情,但我会尝试猜测。我将猜测 Color option
类型为Color
,其中White
是包含Black
,Option.get( ... )
和某些内容的枚举其他颜色。
如果确实如此,则不需要匹配paintArr.[i,j].color
,而是匹配Black
本身,并处理三种情况:(1)当Some
包含在White
中时},(2)当颜色为Some
包裹在None
时,以及(3)当颜色为 for i = 0 to 5 do
match paintArr.[i,j].color with
| Some White -> white <- Array.append white paintArr.[i,j]
| Some Black -> black <- Array.append black paintArr.[i,j]
| None -> ()
时:
i
最后,我可以看到j
的循环,但 for i = 0 to 5 do
for j = 0 to 5 do
match paintArr.[i,j].color with
| Some White -> white <- Array.append white paintArr.[i,j]
| Some Black -> black <- Array.append black paintArr.[i,j]
| None -> ()
在哪里?我想你只是忘了为它添加一个循环:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions"
Version="1.0.6" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
答案 1 :(得分:2)
对于不同的返回类型,我建议使用discriminated unions。您还可以阅读更多here。 但是根据您提供的代码,它似乎与问题本身不匹配。我建议首先重构你的初始函数,使其更清晰。