1

私は本当に取り除きたいコードの繰り返しがあります-

// here's some lib code the repetitive code relies on...

module Option

let definitize opts = List.choose id opts

// here's the start of another file...

module Ast

type Expr =
| Violation of Expr
| Boolean of bool
| String of string

// here's the repetitive code...

let exprToOptViolation expr = match expr with | Violation v -> Some v | _ -> None
let exprToOptBoolean expr = match expr with | Boolean b -> Some b | _ -> None
let exprToOptStr expr = match expr with | String n -> Some n | _ -> None

let exprsToOptViolationStrs exprs = List.map exprToOptViolation exprs
let exprsToOptBools exprs = List.map exprToOptBoolean exprs
let exprsToOptStrs exprs = List.map exprToOptStr exprs

let exprsToViolationStrs exprs =
    let optViolationStrs = exprsToOptViolationStrs exprs
    let violationStrs = Option.definitize optViolationStrs
    (optViolationStrs, violationStrs)    

let exprsToBools exprs =
    let optBools = exprsToOptBools exprs
    let bools = Option.definitize optBools
    (optBools, bools)

let exprsToStrs exprs =
    let optStrs = exprsToOptStrs exprs
    let strs = Option.definitize optStrs
    (optStrs, strs)

ご覧のとおり、これは同じアルゴリズムを3回繰り返したものです。ただし、のような破壊機能を渡す必要があるコードを一般化する方法がわかりませんmatch expr with | destructureFn a -> Some a | _ -> None。誰かが助けることができますか?私は実際にコードに5回の繰り返しがあり(そして成長している)、それを因数分解する必要があります。

乾杯!

* 結論 *

descoの答えを使用して、私はこのリファクタリングに到達しました-

let exprsToValues exprToOptValue exprs =
    let optValues = List.map exprToOptValue exprs
    let values = Option.definitize optValues
    (optValues, values)

let exprsToViolationStrs exprs = exprsToValues (fun expr -> match expr with | Violation v -> Some v | _ -> None) exprs
let exprsToBools exprs = exprsToValues (fun expr -> match expr with | Boolean b -> Some b | _ -> None) exprs
let exprsToStrs exprs = exprsToValues (fun expr -> match expr with | String s -> Some s | _ -> None) exprs

ありがとうdesco!

4

2 に答える 2

2

実際のコードを見ずに推論するのはかなり複雑です、おそらくこのようなものがうまくいくでしょう

type E = | Violation of string | Boolean of bool | String of string
module Option = 
    let definitize vOpt = vOpt |> List.map (function Some x -> sprintf "%A" x | _ -> "none")

let mkEToViolationsStr f exprs = 
    let optViolationStrs = List.map f exprs
    let violationStrs = Option.definitize optViolationStrs
    (optViolationStrs, violationStrs)    

let exprsToViolationStrs2 = mkEToViolationsStr (function Violation v -> Some v | _ -> None)
let exprsToBools2 = mkEToViolationsStr (function Boolean b -> Some b | _ -> None)
let exprsToStrs2 = mkEToViolationsStr (function String s -> Some s | _ -> None)
于 2011-12-13T19:18:28.600 に答える
1

私は間違っているかもしれませんoptValues

let optValues = List.map exprToOptValue exprs

不要のようです。Expr optionstring optionまたはいずれの場合も返されるbool optionため、使用がより困難になります。exprs後で計算を行うために、それを保持して返すか、次のようにします。

let exprsToValues exprToOptValue exprs =
    let values = List.choose exprToOptValue exprs
    (exprs, values)

または単に戻るvaluesだけです。後者の場合、exprsToSomething関数の意味はそれらの名前に完全に適合します。

let exprsToViolationStrs exprs = List.choose (function | Violation v -> Some v | _ -> None) exprs
let exprsToBools exprs = List.choose (function | Boolean b -> Some b | _ -> None) exprs
let exprsToStrs exprs = List.choose (function | String s -> Some s | _ -> None) exprs
于 2011-12-13T21:30:07.767 に答える