2011-12-13 5 views
1

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

// 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 повторений в моем коде (и растет), которые нужно учесть.

Cheers!

* ЗАКЛЮЧЕНИЕ *

Используя ответ 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!

+1

Пожалуйста, покажите свои типы. – Daniel

+0

Готово. Пожалуйста, дайте мне знать, сохраняются ли предположения о нижеследующем ответе. –

+0

Решение desco будет работать. Вы можете опустить 'definitize' и вместо этого использовать' List.choose id'. – Daniel

ответ

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) 
+0

Да. Ты подтолкнул меня на это. Ключ передает функцию деструктурирования для создания карты. – Daniel

+0

Я не знаю, влияет ли это на ваш ответ, но единственное предположение, что вы ошибаетесь в определении definitize. Это - 'let definitize opts = let somes = List.filter Option.isSome выбирает в List.map (fun (opt: 'a option) -> opt.Value) somes' –

+0

@BryanEdds: Ваше определение' definitize' эквивалентно на «List.choose». – Daniel

1

Может быть, я ошибаюсь, но 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 
+0

Да, это даже лучше, если я немного переработаю код. Я определенно был пойман каким-то небрежным мышлением здесь. Благодаря! –

 Смежные вопросы

  • Нет связанных вопросов^_^