Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Union Case Parameterization

I'm just looking at my code, and I'm not certain if there is a way to generalize these code blocks:

The problem that I have is that I'm relatively new to functional paradigm / F#, and I'm not sure if there is a way of processing Union Cases beyond pattern matching / discrimination. This example may ask the question of why these are different cases if they follow the same logic, and the answer is that really I'm trying to use different Cases in a union for Domain Description purposes; I am still trying to find the balance in aiming to create some generalized modules, but make use of Type-safety for domain particularities. In this example, I am bind all possible fields for this Domain usage from a generalized Input module.

Essentially, is there some way of using the Particular Case as a parameter? How would it be passed/piped in?

let updateUserRegistrationInputFieldValue changeValue fieldValue =
    match changeValue with
    | ID cv -> match fieldValue with | ID _ -> ID cv | _ -> fieldValue
    | Name cv -> match fieldValue with | Name _ -> Name cv | _ -> fieldValue
    | Email cv -> match fieldValue with | Email _ -> Email cv | _ -> fieldValue
    | Phone cv -> match fieldValue with | Phone _ -> Phone cv | _ -> fieldValue

let validateUserRegistrationInputField requirementsSelector fieldValue =
    match fieldValue with
    | ID fv -> validateInputValue fv (requirementsSelector fv)
    | Name fv -> validateInputValue fv (requirementsSelector fv)
    | Email fv -> validateInputValue fv (requirementsSelector fv)
    | Phone fv -> validateInputValue fv (requirementsSelector fv)

This is is not critical, as it works and I also believe there is some value in the additional description of fields in these domain particular functions. However, I'm more just trying to see if there is a better practice then what I'm currently doing. The goal is to potentially allow me to build some more generalized functions that I could then keep Domain Description more exclusively in DU Type Definitions but that work with functions that are general.

Any thoughts or input are appreciated...

UPDATE: Fixed some typos, and clarified a little bit more of my goal. Also added the DU Definition that is used in the initial example.

type UserRegistrationInputValue =
    | ID of InputStringValue
    | Name of InputStringValue
    | Email of InputStringValue
    | Phone of InputStringValue

This type is used for both the 'changeValue' and 'fieldValue' parameters in the first function, while it is the fieldValue in the second one. (requirementsSelector is a function that takes this DU Type as a parameter)

The definition of the DU speaks to the level of Domain specificity I'm aiming to achieve, while relying on my generalized modules for processing/behavior. The named/defined functions in the example are being kept in my Domain, because they use the Domain specific types; however, I see, on my current course, repeating this code a lot for the different Domain definitions...

like image 911
SteelCityRKP Avatar asked Jan 18 '26 02:01

SteelCityRKP


1 Answers

You can put multiple items into a tuple before pattern matching and match on them both at once. This gives you an "AND" pattern match:

let updateUserRegistrationInputFieldValue changeValue fieldValue =
    match changeValue, fieldValue with
    | ID cv, ID _ -> ID cv  // matches when changeValue is ID **AND** fieldValue is ID
    | Name cv, Name _ -> Name cv
    | Email cv, Email _ -> Email cv
    | Phone cv, Email _ -> Phone cv
    | _ -> fieldValue

You can put vertical pipes | in pattern matches as an "OR" pattern match:

let validateUserRegistrationInputField requirementsSelector fieldValue =
    match fieldValue with
    | ID fv | Name fv | Email fv | Phone fv ->
        validateInputValue fv (requirementsSelector fv)

If you do this then all of the patterns being "OR"ed need to bind values with the same names and types. In this case, fv must be the same type for all of the DU cases.

like image 177
TheQuickBrownFox Avatar answered Jan 21 '26 07:01

TheQuickBrownFox



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!