F#: shortest way to convert a string option to a string - f#

The objective is to convert a string option that comes out of some nicely typed computation to a plain string that can then be passed to the UI/printf/URL/other things that just want a string and know nothing of option types. None should just become the empty string.
The obvious way is to do a match or an if on the input:
input |> fun s -> fun s -> match s with | Some v -> v | _ -> "" or
input |> fun s -> if s.IsSome then s.Value else ""
but while still being one-liners, these still take up quite a lot of line space. I was hoping to find the shortest possible method for doing this.

You can also use the function defaultArg input "" which in your code that uses forward pipe would be:
input |> fun s -> defaultArg s ""
Here's another way of writing the same but without the lambda:
input |> defaultArg <| ""
It would be better if we had a version in the F# core with the arguments flipped. Still I think this is the shortest way without relaying in other libraries or user defined functions.
UPDATE
Now in F# 4.1 FSharp.Core provides Option.defaultValue which is the same but with arguments flipped, so now you can simply write:
Option.defaultValue "" input
Which is pipe-forward friendly:
input |> Option.defaultValue ""

The obvious way is to write yourself a function to do it, and if you put it in an Option module, you won't even notice it's not part of the core library:
module Option =
let defaultTo defValue opt =
match opt with
| Some x -> x
| None -> defValue
Then use it like this:
input |> Option.defaultTo ""

The NuGet package FSharpX.Extras has Option.getOrElse which can be composed nicely.
let x = stringOption |> Option.getOrElse ""

The best solution I found so far is input |> Option.fold (+) "".
...which is just a shortened version of input |> Option.fold (fun s t -> s + t) "".
I suspect that it's the shortest I'll get, but I'd like to hear if there are other short ways of doing this that would be easier to understand by non-functional programmers.

Related

Is it possible to define an F# operator that applies multiple functions to a single argument (almost the opposite of the ||> operator)?

My attempt to do this is here (forgive the for loop - I was just curious to see if this was possible):
let (|>>) a (b : ('a -> unit) list) =
for x in b do
x a
but when I try to use it I get the error
That None of the types error message can occur if the function you're trying to use is defined further down the file or isn't imported correctly. Otherwise, your function definition seems ok.
I would discourage the use of a custom operator for this. I think they should be used very rarely. This one doesn't seem general enough to be worth defining and could make code hard to read. Here is one alternative:
[ printf "%A"; printfn "%A" ] |> List.iter ((|>) 1)
But it's even clearer and shorter to write out your operator definition inline:
for f in [ printf "%A"; printfn "%A" ] do f 1

What is the best way to do extensive null checks in F# when calling C# code

I would like to know the best way to interact with C# code from F# in a functional way, when I have to check null many times.
From C#, is easy because I have null operator
public bool Authorize(DashboardContext dashboardContext)
{
var context = new OwinContext(dashboardContext.GetOwinEnvironment());
var user = context.Authentication.User;
return user?.Identity?.IsAuthenticated ?? false;
}
From F#, I made this
let authorize (ctx:DashboardContext) =
match OwinContext(ctx.GetOwinEnvironment()) with
| null -> false
| c -> match c.Authentication.User with
| null -> false
| user -> user.Identity.IsAuthenticated
But I am not happy with this. What is the functional way for doing this right? I thought maybe some computation expression would help, but I don't know how to accomplish yet.
Option.ofObj will convert a nullable object into an Option. Then you can use the helpers already defined in the Option module. For example, part of the pattern that you've written there is already encapsulated by Option.bind.
let authorize (ctx:DashboardContext) =
ctx.GetOwinEnvironment() |> OwinContext |> Option.ofObj
|> Option.bind (fun c -> c.Authentication.User |> Option.ofObj)
|> Option.map (fun user -> user.Identity.IsAuthenticated)
|> Option.defaultValue false
Option.bind takes an Option<'a> and a function that takes the type 'a and returns an Option<'a>. When it is used in a pipeline it's a way of "mapping" a Some or filtering it out into a None.
I would say that the function you wrote looks fine actually, but this way might be considered a little bit more idiomatic, though it's arguably also a bit harder to follow in this example. Option.bind really comes into its own when it saves multiple levels of nesting.
It's worth noting that in both your F# function and mine we're assuming non-nullness of the Authentication and Identity properties and risking null reference exceptions when accessing their properties. That's in contrast to the C# method using null propagation. There isn't currently a built-in way to do that in F# but there are probably some advanced methods for simulating it.
It is also possible to do this with computation expressions. See the MaybeBuilder here.
I liked TheQuickBrownFox's idea of using Option.ofObj, but I still found it tedious to write with the built-in functions, so I wrote a custom operator to chain null checks:
let inline (>>?) f g = f >> Option.bind (g >> Option.ofObj)
With this operator, what in C# would be
user?.Identity?.IsAuthenticated ?? false
Becomes:
user
|> (Option.ofObj
>>? (fun x -> x.Identity)
>>? (fun x -> x.IsAuthenticated)
>> Option.defaultValue false)
Which is much prettier!
Disclaimer: I've been using F# for maybe two or three weeks total, so this might be completely stupid :)

How to write efficient list/seq functions in F#? (mapFoldWhile)

I was trying to write a generic mapFoldWhile function, which is just mapFold but requires the state to be an option and stops as soon as it encounters a None state.
I don't want to use mapFold because it will transform the entire list, but I want it to stop as soon as an invalid state (i.e. None) is found.
This was myfirst attempt:
let mapFoldWhile (f : 'State option -> 'T -> 'Result * 'State option) (state : 'State option) (list : 'T list) =
let rec mapRec f state list results =
match list with
| [] -> (List.rev results, state)
| item :: tail ->
let (result, newState) = f state item
match newState with
| Some x -> mapRec f newState tail (result :: results)
| None -> ([], None)
mapRec f state list []
The List.rev irked me, since the point of the exercise was to exit early and constructing a new list ought to be even slower.
So I looked up what F#'s very own map does, which was:
let map f list = Microsoft.FSharp.Primitives.Basics.List.map f list
The ominous Microsoft.FSharp.Primitives.Basics.List.map can be found here and looks like this:
let map f x =
match x with
| [] -> []
| [h] -> [f h]
| (h::t) ->
let cons = freshConsNoTail (f h)
mapToFreshConsTail cons f t
cons
The consNoTail stuff is also in this file:
// optimized mutation-based implementation. This code is only valid in fslib, where mutation of private
// tail cons cells is permitted in carefully written library code.
let inline setFreshConsTail cons t = cons.(::).1 <- t
let inline freshConsNoTail h = h :: (# "ldnull" : 'T list #)
So I guess it turns out that F#'s immutable lists are actually mutable because performance? I'm a bit worried about this, having used the prepend-then-reverse list approach as I thought it was the "way to go" in F#.
I'm not very experienced with F# or functional programming in general, so maybe (probably) the whole idea of creating a new mapFoldWhile function is the wrong thing to do, but then what am I to do instead?
I often find myself in situations where I need to "exit early" because a collection item is "invalid" and I know that I don't have to look at the rest. I'm using List.pick or Seq.takeWhile in some cases, but in other instances I need to do more (mapFold).
Is there an efficient solution to this kind of problem (mapFoldWhile in particular and "exit early" in general) with functional programming concepts, or do I have to switch to an imperative solution / use a Collections.Generics.List?
In most cases, using List.rev is a perfectly sufficient solution.
You are right that the F# core library uses mutation and other dirty hacks to squeeze some more performance out of the F# list operations, but I think the micro-optimizations done there are not particularly good example. F# list functions are used almost everywhere so it might be a good trade-off, but I would not follow it in most situations.
Running your function with the following:
let l = [ 1 .. 1000000 ]
#time
mapFoldWhile (fun s v -> 0, s) (Some 1) l
I get ~240ms on the second line when I run the function without changes. When I just drop List.rev (so that it returns the data in the other order), I get around ~190ms. If you are really calling the function frequently enough that this matters, then you'd have to use mutation (actually, your own mutable list type), but I think that is rarely worth it.
For general "exit early" problems, you can often write the code as a composition of Seq.scan and Seq.takeWhile. For example, say you want to sum numbers from a sequence until you reach 1000. You can write:
input
|> Seq.scan (fun sum v -> v + sum) 0
|> Seq.takeWhile (fun sum -> sum < 1000)
Using Seq.scan generates a sequence of sums that is over the whole input, but since this is lazily generated, using Seq.takeWhile stops the computation as soon as the exit condition happens.

Better way to get tree representation of directory using F#?

I am new(ish) to F# and am trying to get a tree representation of a filesystem directory. Here's what I came up with:
type FSEntry =
| File of name:string
| Directory of name:string * entries:seq<FSEntry>
let BuildFSDirectoryTreeNonTailRecursive path =
let rec GetEntries (directoryInfo:System.IO.DirectoryInfo) =
directoryInfo.EnumerateFileSystemInfos("*", System.IO.SearchOption.TopDirectoryOnly)
|> Seq.map (fun info ->
match info with
| :? System.IO.FileInfo as file -> File (file.Name)
| :? System.IO.DirectoryInfo as dir -> Directory (dir.Name, GetEntries dir)
| _ -> failwith "Illegal FileSystemInfo type"
)
let directoryInfo = System.IO.DirectoryInfo path
Directory (path, GetEntries directoryInfo)
But... pretty sure that isn't tail recursive. I took a look at the generated IL and didn't see any tail prefix. Is there a better way to do this? I tried using an accumulator but didn't see how that helps. I tried mutual recursive functions and got nowhere. Maybe a continuation would work but I found that confusing.
(I know that stack-depth won't be an issue in this particular case but still would like to know how to tackle this non-tail recursion problem in general)
OTOH, it does seem to work. The following prints out what I am expecting:
let PrintFSEntry fsEntry =
let rec printFSEntryHelper indent entry =
match entry with
| File name -> printfn "%s%s" indent name
| Directory(name, entries) ->
printfn "%s\\%s" indent name
entries
|> Seq.sortBy (function | File name -> 0 | Directory (name, entries) -> 1)
|> Seq.iter (printFSEntryHelper (indent + " "))
printFSEntryHelper "" fsEntry
This should probably be a different question but... how does one go about testing BuildFSDirectoryTreeNonTailRecursive? I suppose I could create an interface and mock it like I would in C#, but I thought F# had better approaches.
Edited: Based on the initial comments, I specified that I know stack space probably isn't an issue. I also specify I'm mainly concerned with testing the first function.
To expand on my comment from earlier - unless you anticipate working with inputs that would cause a stack overflow without tail recursion, there's nothing to be gained from making a function tail-recursive. For your case, the limiting factor is the ~260 characters in path name, beyond which most Windows APIs will start to break. You'll hit that way before you start running out of stack space due to non-tail recursion.
As for testing, you want your functions to be as close to a pure function as possible. This involves refactoring out the pieces of the function that are side-effecting. This is the case with both of your functions - one of them implicitly depends on the filesystem, the other prints text directly to the standard output.
I guess the refactoring I suggest is fairly close to Mark Seemann's points: few mocks - checked, few interfaces - checked, function composition - checked. The example you have however doesn't lend itself nicely to it, because it's an extremely thin veneer over EnumerateFileSystemInfo. I can get rid of System.IO like this:
type FSInfo = DirInfo of string * string | FileInfo of string
let build enumerate path =
let rec entries path =
enumerate path
|> Seq.map (fun info ->
match info with
| DirInfo (name, path) -> Directory(name, entries path)
| FileInfo name -> File name)
Directory(path, entries path)
And now I'm left with an enumerate: string -> seq<FSInfo> function that can easily be replaced with a test implementation that doesn't even touch the drive. Then the default implementation of enumerate would be:
let enumerateFileSystem path =
let directoryInfo = DirectoryInfo(path)
directoryInfo.EnumerateFileSystemInfos("*", System.IO.SearchOption.TopDirectoryOnly)
|> Seq.map (fun info ->
match info with
| :? System.IO.FileInfo as file -> FileInfo (file.Name)
| :? System.IO.DirectoryInfo as dir -> DirInfo (dir.Name, dir.FullName)
| _ -> failwith "Illegal FileSystemInfo type")
You can see that it has virtually the same shape as the build function, minus recursion, since the entire 'core' of your logic is in EnumerateFileSystemInfos which lives beyond your code. This is a slight improvement, not in any way test-induced damage, but still it's not something that will make it onto anyone's slides anytime soon.

Avoid mutation in this example in F#

Coming from an OO background, I am having trouble wrapping my head around how to solve simple issues with FP when trying to avoid mutation.
let mutable run = true
let player1List = ["he"; "ho"; "ha"]
let addValue lst value =
value :: lst
while run do
let input = Console.ReadLine()
addValue player1List input |> printfn "%A"
if player1List.Length > 5 then
run <- false
printfn "all done" // daz never gunna happen
I know it is ok to use mutation in certain cases, but I am trying to train myself to avoid mutation as the default. With that said, can someone please show me an example of the above w/o using mutation in F#?
The final result should be that player1List continues to grow until the length of items are 6, then exit and print 'all done'
The easiest way is to use recursion
open System
let rec makelist l =
match l |> List.length with
|6 -> printfn "all done"; l
| _ -> makelist ((Console.ReadLine())::l)
makelist []
I also removed some the addValue function as it is far more idiomatic to just use :: in typical F# code.
Your original code also has a common problem for new F# coders that you use run = false when you wanted run <- false. In F#, = is always for comparison. The compiler does actually warn about this.
As others already explained, you can rewrite imperative loops using recursion. This is useful because it is an approach that always works and is quite fundamental to functional programming.
Alternatively, F# provides a rich set of library functions for working with collections, which can actually nicely express the logic that you need. So, you could write something like:
let player1List = ["he"; "ho"; "ha"]
let player2List = Seq.initInfinite (fun _ -> Console.ReadLine())
let listOf6 = Seq.append player1List list2 |> Seq.take 6 |> List.ofSeq
The idea here is that you create an infinite lazy sequence that reads inputs from the console, append it at the end of your initial player1List and then take first 6 elements.
Depending on what your actual logic is, you might do this a bit differently, but the nice thing is that this is probably closer to the logic that you want to implement...
In F#, we use recursion to do loop. However, if you know how many times you need to iterate, you could use F# List.fold like this to hide the recursion implementation.
[1..6] |> List.fold (fun acc _ -> Console.ReadLine()::acc) []
I would remove the pipe from match for readability but use it in the last expression to avoid extra brackets:
open System
let rec makelist l =
match List.length l with
| 6 -> printfn "all done"; l
| _ -> Console.ReadLine()::l |> makelist
makelist []

Resources