I’ve been learning F# and functional programming and trying to do things the functional way. However, when it comes to rewriting some code I’d already written in C# I get stuck at simple if-then statements (ones that only do something, not return a value). I know you can pull this off in F#:
if expr then do ()
However, I thought this was an imperative approach to coding? Maybe I’ve not learned enough about functional programming, but it doesn’t seem functional to me. I thought the functional approach was to compose functions and expressions, not simply execute statements one after the other which is what if-then seems to encourage.
So, am I missing something and if-then is perfectly fine in the functional world? If not, what is the functional equivalent of such a statement? How could I take an if-then and turn it functional?
Edit: I might’ve asked the wrong question (sorry, still fairly new to functional programming): Let’s take a real world example that made me even ask this:
if not <| System.String.IsNullOrWhiteSpace(data) then do
let byteData = System.Text.Encoding.Unicode.GetBytes(data)
req.ContentLength <- int64 byteData.Length
let postStream : System.IO.Stream = req.GetRequestStream()
postStream.Write(byteData, 0, byteData.Length)
postStream.Flush()
postStream.Dispose()
The body of that if-then doesn’t return anything, but I don’t know how I could make this more functional (if that’s even possible). I don’t know the proper technique for minimizing imperative code. Given F#’s nature it’s fairly easy to just transport my C# directly, but I’m having difficulties turning it functional. Every time I reach such an if statement in C#, and I’m trying to transport it to F#, I get discouraged that I can’t think of a way to make the code more functional.
An important point that hasn’t been mentioned so far is the difference between
if .. then .. elseandif .. thenwithout theelsebranch.Ifin functional languagesThe functional interpretation of
ifis that it is an expression that evaluates to some value. To evaluate the value ofif c then e1 else e2you evaluate the conditioncand then evaluate eithere1ore2, depending on the condition. This gives you the result of theif .. then .. else.If you have just
if c then e, then you don’t know what the result of the evaluation should be ifcisfalse, because there is noelsebranch! The following clearly does not make sense:In F#, expressions that have side-effects like
printf "hi"return a special value of typeunit. The type has only a single value (written as()) and so you can writeifwhich does an effect in just a single case:This always evaluates to
unit, but in thetruebranch, it also performs the side-effect. In thefalsebranch, it just returns aunitvalue. In F#, you don’t have to write theelse ()bit by hand, but conceptually, it is still there. You can write:Regarding your additional example
The code looks perfectly fine to me. When you have to deal with API that is imperative (like lots of the .NET libraries), then the best option is to use the imperative features like
ifwith aunit-returning branch.You can use various tweaks, like represent your data using
option<string>(instead of juststringwithnullor empty string). That way, you can useNoneto represent missing data and anything else would be valid input. Then you can use some higher-order functions for working with options, such asOption.iter, which calls a given function if there is a value:This is not really less imperative, but it is more declarative, because you don’t have to write the
ifyourself. BTW: I also recommend usinguseif you want toDisposeobject auotmatically.