gpt4 book ai didi

f# - 在 F# 中使用 bool 函数作为模式鉴别器

转载 作者:行者123 更新时间:2023-12-04 10:03:18 24 4
gpt4 key购买 nike

我试着用谷歌搜索这个,但我找不到引导我做我想做的事情的词集。

我正在尝试解决 Project Euler Problem 54 ,我有这个相当可笑的功能:

let evaluate hand =
if isRoyalFlush hand then 9
elif isStraightFlush hand then 8
elif isFour hand then 7
elif isFullHouse hand then 6
elif isFlush hand then 5
elif isStraight hand then 4
elif isThree hand then 3
elif isTwoPair hand then 2
elif isPair hand then 1
else 0

所有 isSomething关键字是采用 string array 的函数并返回一个 bool 值。是否有更优雅的方式使用模式匹配来做到这一点?

这不起作用:
match true with
| isRoyalFlush hand -> 9
| isStraightFlush hand -> 8
// .. etc

我正在寻找这样的东西:
match hand with 
| isRoyalFlush -> 9
| isStraightFlush -> 8
// .. etc

我记得曾经看到过类似的东西,但我不记得在哪里或如何找到它。

最佳答案

您要active patterns :

let (|IsRoyalFlush|_|) hand =
if isRoyalFlush hand then Some () else None

let (|IsStraightFlush|_|) hand =
if isStraightFlush hand then Some() else None

// etc.

match hand with
| IsRoyalFlush -> 9
| IsStraightFlush -> 8
// etc.

或者更好的是,将所有通用代码提取到一个简单的事件模式构建器中:
let toActivePattern pred x =
if pred x then Some () else None

let (|IsRoyalFlush|_|) = isRoyalFlush |> toActivePattern
let (|IsStraightFlush|_|) = isStraightFlush |> toActivePattern
// etc.

match hand with
| IsRoyalFlush -> 9
| IsStraightFlush -> 8
// etc.

如果您不了解第二个示例的工作原理,请发表评论,我将深入探讨。

将事件模式组合在一起

由于事件模式只是函数,您可以使用标准函数组合将它们连接在一起。嗯,几乎是标准的函数组合。与 >> 的普通函数组合运算符的意思是“取函数 1 的结果,并将其用作函数 2 的输入”。但在这里,函数 1 和函数 2 都返回 Some () ,但取一个整数;您不能将 1 的输出传递到 2 的输入中,因为它们不是兼容的类型。但我们实际上想要的是将相同的输入传递给两个函数,并将它们的输出组合起来。

因此,我们将定义自己的函数,而不是使用正常的函数组合,该函数采用两个事件模式,并返回 Some ()如果两种模式都匹配输入:
let matchesBoth pattern1 pattern2 x =
match pattern1 x with
| None -> None
| Some _ -> pattern2 x

在此期间,让我们定义一个自定义运算符,以便您了解其工作原理。此 matchesBoth功能与 && 非常相似运算符,因为它将返回 Some ()仅当两种模式都返回 Some ()对于任何给定的输入 x .我们不应该重载 &&运算符采用不同的类型,因此让我们创建一个类似于 && 的自定义运算符,但提醒我们它结合了两种事件模式。如果我们的运算符看起来像 |&&| ,那应该是完美的。所以让我们创建它:
let (|&&|) = matchesBoth

就是这样!现在我们可以做这样的事情:
let (|Div3|_|) n =
if n % 3 = 0 then Some () else None

let (|Div5|_|) n =
if n % 5 = 0 then Some () else None

let (|Div15|_|) = (|Div3|_|) |&&| (|Div5|_|)

let fizzbuzz n =
match n with
| Div15 -> "FizzBuzz"
| Div5 -> "Buzz"
| Div3 -> "Fizz"
| _ -> string n

fizzbuzz 30 // Result: "FizzBuzz"
fizzbuzz 31 // Result: "31"

或者,对于您的示例:
let (|IsStraightFlush|_|) = (|IsStraight|_|) |&&| (|IsFlush|_|)

关于f# - 在 F# 中使用 bool 函数作为模式鉴别器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39262053/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com