type Something = Something of int
let fromInt something = Something something
let asOption something =
if something = 0 then
None
else
Some (something |> fromInt)
…but then I changed ‘asOption’ to:
let asOption something =
if something = 0 then
None
else
something |> fromInt |> Some
Which do you think is ‘better’?
I kind of like the way that None/Some start the lines in the first example, makes it more obvious it’s going to be an Option if you only look at that line, but the pipeline seems more idiomatic for F#.
Is there an even better way to do this?
Am I worrying too much about this?
let asOption =
function
| 0 -> None
| value -> Some(Something value)
or
let asOption something =
match something with
| 0 -> None
| value -> Some(Something value)
I know in my early F# days I overused the pipe operator; in your code, I don’t feel it is needed to use the operator. It is better to use it for things that are laid out on several lines, or if you are doing things like in your code on a single line, it would be to keep a structure similar over several bindings that are next to each others.
Am I worrying too much about this?
Probably, if you are starting with F#, take it easy and just get your code to do what you need it to, there will come a time where you’ll revisit and do adjustments based on your journey with the language
I was starting to think that, by analogy, I was building a town and worrying more about the typeface to be used on the street signs than about whether the streets took people to places they wanted to go.
I was having the same sort of concern with Results, e.g.
try
…
with
| exn -> Error (SomethingError.UnhandledError exn)
Now I prefer the pipeline here, and if Don disagrees so be it. I like that it shows the transformation in the order it happens from left to right. And the compiler should optimise the pipeline operators away. (if it doesn’t, it should)
In the other form it is completely backwards from the sequence that is intended and even needs brackets because otherwise it wouldn’t be unambiguous.
If it were simple enough that brackets weren’t needed e.g. exn -> Error exn then it makes me feel less icky and I’ll go with it.
While I like the idea of having the ‘eventual type’ at the start of the line (easier to see what’s going to happen eventually) I also like the idea of using the pipeline to show the ‘encapsulation flow’ of types within types (read to the end to see what happens).
A ‘hybrid’ style – ‘up-front’ when only one pipe would be required (e.g. Error exn) and pipeline otherwise (exn |> MyError |> Error), may also be an option.
I think I’ll probably end up ‘flip-flopping’ between different styles as I (hopefully) become more proficient in F# and eventually come up with a style that I like, maybe without realising that I’ve made a decision.