Как абстрагироваться от деструктуризации в F # - PullRequest
1 голос
/ 13 декабря 2011

У меня есть некоторое повторение кода, от которого я действительно хочу избавиться -

// 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!

Ответы [ 2 ]

2 голосов
/ 13 декабря 2011

довольно сложно рассуждать, не видя реальный код, возможно что-то вроде этого будет работать

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)
1 голос
/ 14 декабря 2011

Я могу ошибаться, но optValues в

let optValues = List.map exprToOptValue exprs

кажется ненужным.В каждом случае он возвращает Expr option, string 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...