F# pattern matching on records with optional fields -


The 'option' of F # is a good way to use type systems to isolate the data that It may be known to exist that it is not present, and the manner in which I apply the match expression, all the cases are considered:

  Match with str Some S - & gt; Function teaking string (s) | None - & gt; The "Abc" // compiler will complain helpful if this line was not present.  

It is very useful that s ( str ) Is a string instead of a string option .

However, while working with archives with optional fields ...

  type SomeRecord = {field1: string field2: string option}  

... and filtering those records, a match expression < / Em> is unnecessary, because is not able to do this in any case, but this ...

  functionTakingSequenceOfRecords mySeq = mySeq | & Gt; Seq.filter (funny record -> record.field 2.som). & Gt; Seq.map will not compile  

... because the record where field2 will not compile. No 'Population' has been filtered, the type of field2 is still string option , not string .

I could define another record type, where field2 is not optional, but this approach looks complicated, and can be ineffective with many optional fields.

I have defined an operator which is an exception if any option any ...

  inline (|?!) (Value) : 'One option) (Message: string) = Match value. Some x - & gt; X | None - & gt; InvalidOp message  

... and the previous code has been changed to ...

  function TakingSequenceOfRecords mySeq = mySeq | & Gt; Seq.filter (funny record -> record.field 2.som). & Gt; Seq.map (Function Record -> Functional String (record.field2 |?! Should never be ")) // Now  

compiled ... but it does not look ideal . Instead of raising an exception, I can use Unchecked.default , but I'm not sure that it would be better, its root is that any case after the filter is relevant is not.

Is there any better way to deal with this?

Edit

Very interesting answers brought my carefully recorded accounting patterns, which I did not know, and value , Which I had seen but misunderstood (I think it throws a NullReferenceException if none ) But I think my example may be bad, because using more than one field from my more complex, real-life problem record involves using. I suspect that I'm stuck like something ...

  | & Gt;  
"post-text" itemprop = "text">

In this example, you It can be used:

  function TakingSequenceOfRecords mySeq = mySeq | & Gt; Seq.choose (Funny {Field 2 = V} - & gt; v). & Gt; Seq.map functionTakingString  

Seq.choose allows us to filter items based on optional results. For more compressed code we match in the records.

I think the general idea is to manipulate the option values ​​using the organizers, high-order functions, unless you want to change them in other types of values ​​(eg in this case < Code> Seq.choose ). Your | ??! Use of is frustrating because it is a partial operator (throwing an exception in some cases) You can argue that it is safe to use it in this special case; But the F # type system can not recognize it and warn you about any unsafe use in any case.

One way to note, I would like to take a look at the railway oriented programming series. The series shows you that you are safe-looking and organized to handle errors, where you can keep diagnostic information.

UPDATE (on your edit):

A The modified version of your function has been written as follows:

 < Using the code> function SequenceOfRecords mySeq = mySeq | & Gt; Seq.choose (Fun {Field 1 = v1; field2 = v2} -> v2 | & gt; Option.map (functionTracking string v1))  

This explains that common ideas I mentioned where you manipulate the option value using the high-order functions ( option.map ) and convert them to the last step ( Seq.choose ).


Comments

Popular posts from this blog

python - Overriding the save method in Django ModelForm -

html - CSS autoheight, but fit content to height of div -

qt - How to prevent QAudioInput from automatically boosting the master volume to 100%? -