F#常量模式匹配和检查消除

Zin*_*ust 5 f# functional-programming pattern-matching

我对F#世界很陌生,目前正试图尝试功能.试图找到新的技术,使它们更紧凑和灵活,并从C#类似的编码风格.所以我有一个非常难看的代码,我不断检查和模式匹配:

type StringChecking =
    | Success of string
    | Fail

    let StringProcessor(str : string) =
        let newstr = modifyFn str
        let result = checkFn newstr
        match result with
        | true -> Success result
        | false ->
            let newstr' = modifyFn' str
            let result' = checkFn newstr'
            match result' with
            | true -> Success newstr'
            | false -> 
                let newstr'' = modifyFn'' str
                let result'' = checkFn newstr''
                match result'' with
                | true -> Success newstr''
                | false -> 
                    Fail
Run Code Online (Sandbox Code Playgroud)

是否有一些有用的技术可以帮助我消除所有这些阶段,使我的代码更优雅.对不起,如果问题看起来很尴尬或愚蠢,但我真的想对这个问题做些什么,因为我想在我的某个项目中使用它.我已经厌倦了在C#中不断检查.感谢您的时间和建议.

kae*_*fer 5

成功之路

在此输入图像描述

这假设目标是在一系列步骤中重复转换对象,此时仅在成功完成前一步骤时才执行下一步骤.这将由F#的Option类型封装在这里.

如果你在简洁之后,你可能会比某种一元的束缚更糟糕.

let (>>=) arg f =   // bind operator
    match arg with
    | Some x -> f x
    | None -> None

let checkWith checker x =
    if checker x then Some x else None
"sample String"
|> (modifyFn >> checkWith checkFn)
>>= (modifyFn' >> checkWith checkFn')
>>= (modifyFn'' >> checkWith checkFn'')
Run Code Online (Sandbox Code Playgroud)

但你确实注意到流水线操作的第一步.这是由计算开始时的展开值产生的.从而:

Success "sample String"
>>= (modifyFn >> checkWith checkFn)
>>= (modifyFn' >> checkWith checkFn')
>>= (modifyFn'' >> checkWith checkFn'')
Run Code Online (Sandbox Code Playgroud)

如果您想要修改和验证相同的原始值而不是上一步的结果,那么我们只需忽略它.

let str ="sample String"
modifyFn str |> checkWith checkFn
>>= (fun _ -> modifyFn' str |> checkWith checkFn')
>>= (fun _ -> modifyFn'' str |> checkWith checkFn'')
Run Code Online (Sandbox Code Playgroud)

替代路径

在此输入图像描述

如果计算在步骤成功完成时终止,否则继续执行替代步骤,我们将具有不同的签名.类似于F#的defaultArg函数(arg:'T option -> defaultvalue:'T > 'T),我将提出类似绑定defaultBy:

let defaultBy c a f =
    match a with
    | None -> f c
    | x -> x
let (>?=) f = defaultBy "sample string" f

"sample string"
|> (modifyFn >> checkWith checkFn)
>?= (modifyFn' >> checkWith checkFn')
>?= (modifyFn'' >> checkWith checkFn'')
Run Code Online (Sandbox Code Playgroud)