types - F#在模式匹配中返回不同的类型

标签 types f# pattern-matching

我试图弄清楚如何处理模式匹配情况,它根据匹配返回不同的类型,我知道它必须为每个分支返回相同的类型,所以我不确定处理一个“正确”的方法是什么这样的情况是:

我试图在下面举例说明我的困惑,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)

所以基本上,我认为我的问题归结为:您如何处理这样的情况,在某些情况下,我会得到一场需要我什么都不做的比赛,或者可能只是与其他情况不同的事情?

最佳答案

序言:对我来说很明显你对 F# 非常缺乏经验。如果这是真的,我建议你先阅读某种书籍或一组教程(我总是推荐 https://fsharpforfunandprofit.com/)。您正在尝试使用比初学者应该处理的更复杂的代码。


好的,现在来看看实际的答案

首先,请注意 Array.append不会“更改”(“更新”、“修改”)数组,而是返回一个新数组 - 您给它的原始数组和新元素的串联。有了这些知识,很容易看出您的 Array.append调用是无用的:它们会返回一些东西,但你会立即将其丢弃。

从上下文中,我了解您实际上想要做的是用它的扩展版本替换有问题的数组。为此,您需要声明您的数组 mutable ,然后使用“破坏性更新”运算符<- :

black <- Array.append black paintArr.[i,j]

破坏性更新运算符 <-在 F# 中相当于赋值语句 =在类 C 语言中。

现在,如果您像这样使用破坏性更新运算符,则该表达式的结果类型将是 unit - 一个空类型,用于表示“无值(value)”。这种类型只有一个值,写成两个括号,括号之间没有任何内容。例如:

> let x = ()
val x : unit = ()

所以要实现“所有分支的相同类型”规则,您可以让第三个分支简单地返回 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].colorColor option 类型, 其中 Color是一个包含 White 的枚举, Black ,以及其他一些颜色。
如果是这样,您需要在 Option.get( ... ) 上不匹配, 但在 paintArr.[i,j].color本身,并处理三种情况:(1)当颜色为Black时包裹在 Some , (2) 当颜色为 White包裹在 Some , 和 (3) 当颜色为 None 时:

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

关于types - F#在模式匹配中返回不同的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48157513/

相关文章:

sql - 获取 PostgreSQL 中小数点后非零的记录

f# - 速度问题 : Creating Series with Deedle/Getting unique values in F#

linux - 如何在 Linux 上测试 F#

performance - fromJust 定义中的模式匹配

unix - 使用 grep 在文件中查找二进制模式

python - 在 python 中的 bytes() 调用中用方括号括住整数意味着什么?

data-structures - Haskell 和条件数据结构

F# 惰性求值 vs 非惰性求值

javascript - Switch 中的 ES6 模式匹配

mysql - 用于存储连续时间计数器的数据类型?