gpt4 book ai didi

f# - 我是否正确使用函数组合?

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

为了理解函数式编程的能力,我整理了一些基本函数,您可以将它们组合在一起来构建复杂的正则表达式。现在经过一些测试,我发现这可行,但是您可以用任何可行的语言编写一些可怕的代码。这是您会发现专业 F# 程序员编写的那种代码还是我滥用了该功能?

注:test具体就是我所指的。

type State = { input:string; index:int; succeeded:bool }
type Matcher = State -> State

let term (cs:char Set) =
fun s ->
if s.succeeded && s.index < s.input.Length && cs.Contains s.input.[s.index] then
{ input = s.input; index = s.index + 1; succeeded = true }
else
{ input = s.input; index = s.index; succeeded = false }

let quantify (term, min, max) =
let rec inner (s:State, count) =
if s.succeeded && s.index < s.input.Length && count <= max then
inner (term { input = s.input; index = s.index + 1; succeeded = true }, count + 1)
elif count >= min && count <= max then
{ input = s.input; index = s.index - 1; succeeded = true }
else
s
fun s -> inner (s, 0)

let disjunction leftTerm rightTerm =
fun s ->
let left = leftTerm s
if not left.succeeded then
let right = rightTerm s
if not right.succeeded then
{ input = s.input; index = s.index; succeeded = false }
else
right
else
left

let matcher input terms =
let r = terms { input = input; index = 0; succeeded = true }
if r.succeeded then r.input.Substring (0, r.index) else null

let test = // (abc|xyz)a{2,3}bc
disjunction // (abc|xyz)
(term (set "a") >> term (set "b") >> term (set "c"))
(term (set "x") >> term (set "y") >> term (set "z"))
>> quantify (term (set "a"), 2, 3) // (a{2,3})
>> term (set "b") // b
>> term (set "c") // c

let main () : unit =
printfn "%s" (matcher "xyzaabc" test)
System.Console.ReadKey true |> ignore

main()

最佳答案

代码对我来说看起来很不错。

我不确定这是您的意图还是巧合,但您正在实现与“解析器组合器”非常相似的东西,这是许多学术论文的主题:-)。我认为Monadic Parser Combinators可读性很强(它在 Haskell 中有示例,但您应该能够将它们转换为 F#)。

关于函数组合运算符。我通常不喜欢过多地使用运算符,因为它经常混淆代码。但是,在您的示例中,这很有意义,因为您可以轻松想象 >>意思是“这个组应该跟在那个组后面”,这很容易解释。

我要做的唯一小改动是为 disjunction 选择一些不错的自定义操作符。操作并定义一些更原始的操作,以便您可以编写例如:

// Test against several terms in sequence
let sequence terms = (fun state -> terms |> Seq.fold (>>) state)
// Test for a substring
let substring s = sequence [ for c in s -> term (set [c]) ]

let test = // (abc|xyz)a{2,3}bc
( substring "abc" <|> substring "xyz" )
>> quantify 2 3 (term (set "a")) // (a{2,3})
>> substring "bc" // bc

这是更高级的描述,因此删除了一些 >>运算符支持更具描述性的函数(并封装 >> )。我也换了 quantify采用多个参数而不是三元组(这是一个小改动)

如果你想进一步玩这个,那么你可以看看这篇文章并尝试编写 F# 计算表达式构建器,它允许你使用 parser { .. }句法。

关于f# - 我是否正确使用函数组合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3614461/

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