F# - Converting nested for-loops to a functional style - f#

I'm trying to convert my nested for-loops to a more functional style.
I've been messing around with pipelining, sequences, and arrays, but to no avail.
Here's what I have:
let allCarrierCodes = new List<string>()
for result in getAllCarrierCodesResults do
for carrierCode in result do
allCarrierCodes.Add(carrierCode.ToString())
getAllCarrierCodesResults is a seq of type "obj list"
What's a nice functional way to re-write the nested loops?
Thanks.

You can use Seq.collect:
let allCodes = Seq.collect id getAllCarrierCodesResults
|> Seq.map string)
or
let allCodes = Seq.collect (Seq.map string) getAllCarrierCodesResults
you can then convert the resulting seq<string> into the concrete collection you want.

Lee's answer is better than this, but I just wanted to mention that you can totally just put those nested loops inside a list comprehension, and voila:
let allCarrierCodes =
[for result in getAllCarrierCodesResults do
for carrierCode in result do
yield carrierCode.ToString()]
Looks kind of imperative-ish, but is really functional.
Also, you should use string carrierCode instead of carrierCode.ToString(). Protects you from NRE and looks more functional for added bonus :-)

Related

F# Pipeline operator into an indexer property?

How should one pipeline an index into an indexer property of eg.: a Map?
let aMap = [
(1,'a')
(2,'b')
] |> Map.ofList
let someChar =
1
|> aMap.Item
In the example above, I get the error that "An indexer property must be given at least one argument"
The following works, but in real code gets kind of ugly and strange looking. Is there a better way? What is the language reason for not accepting the pipelined item for the indexer property? is it because it is a getter property instead of a simple method?
let someChar =
1
|> fun index -> aMap.[index]
Edit: below is a better representation of the actual usage scenario with the solution I went with inside a transformation pipeline eg.:
let data =
someList
|> List.map (fun i ->
getIndexFromData i
|> Map.find <| aMap
|> someOtherFunctionOnTheData
)
|> (*...*)
As a rule of thumb, you shouldn't pipeline into an indexer property. Use indexers explicitly.
For F# collections modules, there usually exists a lookup function that can be used instead of index access (Array.get, Map.find, Set.contains).
The Item indexer actually has a an associated getter method get_Item which F# compiler wisely hides from the auto-completion so that people do not use it, but it does allow you to use it:
let aMap =
[ (1,'a')
(2,'b') ] |> Map.ofList
let someChar =
1 |> aMap.get_Item
That said, I cannot imagine a situation where I would want to do this. Pipelines make sense in cases where you're chaining multiple operations on the same data structure (list transformations, etc.), but using pipeline as a general mechanism for invoking an operation is just introducing a more cumbersome syntax for doing a simple thing.
The point of indexers is to make it clear that you are indexing into some collection. Using that directly makes your code much more readable:
let someChar = aMap.[1]

Create sequence from multidimensional array in F#

I'm new to F# and I've been struggling with this for a while. I have a two-dimensional array ([,]) and I want to get a sequence of all the elements in this array. While there seem to be options to iterate such an array (e.g. Array2D.iter), I want to pass the sequence to some other functions, not just iterate the elements.
In the end, I've worked around this with the following function:
let getAllElements (a: MyDiscriminatedUnionType[,]) : (seq<MyDiscriminatedUnionType>) =
seq { for x in a do yield (x :?> MyDiscriminatedUnionType) }
this seems to work but looks very excessive to me. Since the for .. in expression works on an enumerable-expression there already seems to be a way to enumerate a multidimensional array more easily?
Also I can't really figure out how to make this function more generic, so that this isn't tied to MyDiscriminatedUnionType but works with all multi-dimensional arrays.
To answer the second part of your question, you can make the function generic by replacing MyDiscriminatedUnionType type with a generic type parameter such as 'a:
let getAllElements (a:'a[,]) : seq<'a> =
seq { for x in a do yield x :?> 'a }
I think the code is quite clean - it would be nice if there was a built-in function for this (say, Array2D.toSeq) and I think it would be reasonable to suggest this as an addition to the standard F# library, but I don't think there is a function like this - and then the sequence expression is a nice way of writing this.
The only annoying thing is that you have to cast x using x :?> 'a. This is because the 2D array type does not implement a generic IEnumerable<'a> interface, but only the (old style) non-generic version.
You could avoid that by iterating over the indices and indexing into the array, which is a bit longer, but avoids the ugly casting:
let getAllElements (a:'a[,]) : seq<'a> =
seq { for i in 0 .. a.GetLength(0)-1 do
for j in 0 .. a.GetLength(1)-1 do yield a.[i,j] }

Any way to "open Seq" or similar effect?

a
|>Seq.map fixLine
|>Seq.map splitCells
|>Seq.map getName
|>Seq.where(fun a->not<|Seq.isEmpty a)
|>Seq.map fixName
Always find it annoying while keep lots of Seq. in lines. Suggest a good way to omit them...
For example, use List.map for lists, use just map for seq, or split them into different modules when I'm using seq and lists.
a
|>map fixLine
|>map splitCells
|>map getName
|>where(fun a->not<|isEmpty a)
|>map fixName
Looks really better.
You could also just define aliases for the functions you want:
let map = Seq.map
let where = Seq.filter
Or you could make it even more terse by defining your own operators:
let (|!>) s f = Seq.map f s
let (|*>) s f = Seq.filter f s
a
|!> fixLine
|!> splitCells
|!> getName
|*> (fun a->not<|isEmpty a)
|!> fixName
But at this point, your code becomes way too cryptic - i.e. someone looking at the code will have a hard time understanding what's going on.
And finally, you could make the original code look a bit better by noticing that a composition of maps is a map of composition:
a
|> Seq.map (fixLine >> splitCells >> getName)
|> Seq.filter (not << isEmpty)
|> Seq.map fixName
This is the solution that I personally would prefer.
In general, my personal experience shows that, despite the first impulse to "fix" the repetitiveness by making the repetitive parts themselves smaller, there is usually a better solution that would make your code not only look better, but better factored as well.
I don't think there is an easy way to avoid repeating the Seq - this is just one place where F# makes things a bit more explicit (so that you know what's going on).
But you can use the F# Core Fluent library which gives you a more C#-like syntax with .:
a.map(fixLine).map(splitCells).map(getName).filter(isEmpty >> not).map(fixName)

Optionally taking the first item in a sequence

I need a function like Seq.head, but returning None instead of throwing an exception when the sequence is empty, i.e., seq<'T> -> 'T option.
There are a jillion ways to do this. Here are several:
let items = Seq.init 10 id
let a = Seq.tryFind (fun _ -> true) items
let b = Seq.tryPick Some items
let c = if Seq.isEmpty items then None else Some (Seq.head items)
let d =
use e = items.GetEnumerator()
if e.MoveNext() then Some e.Current
else None
b is the one I use. Two questions:
Is there a particularly idiomatic way to do this?
Since there's no built-in Seq.tryHead function, does that indicate this shouldn't be necessary, is uncommon, or is better implemented without a function?
UPDATE
tryHead has been added to the standard library in F# 4.0.
I think (b) is probably the most idiomatic, for the same reason #Ramon gave.
I think the lack of Seq.tryHead just means that it is not super common.
I'm not sure, but my guess is that functional languages with Hindley-Milner type inference in general are sparse about implementing such specific functions on collection types because overloading isn't available and composing higher-order functions can be done tersely.
For example, C# Linq extensions are much more exhaustive than functions in F#'s Seq module (which itself is more exhaustive than functions on concrete collection types), and even has IEnumerable.FirstOrDefault. Practically every overload has a variation which performs a map.
I think emphasis on pattern matching and concrete types like list is also a reason.
Now, most of the above is speculation, but I think I may have a notion closer to being objective. I think a lot of the time tryPick and tryFind can be used in the first place instead of filter |> tryHead. For example, I find myself writing code like the following fairly frequently:
open System.Reflection
let ty = typeof<System.String> //suppose this type is actually unknown at compile time
seq {
for name in ["a";"b";"c"] do
yield ty.GetMethod(name)
} |> Seq.tryFind((<>)null)
instead of like
...
seq {
for name in ["a";"b";"c"] do
match ty.GetMethod(name) with
| null -> ()
| mi -> yield mi
} |> tryHead
You could define:
let seqTryHead s = Seq.tryPick Some s
It is of type seq<'a> -> 'a option. Note that I don't beta-reduce because of the generic value limitation.

F# Sequences - how to return multiple rows

let x = [for p in db.ParamsActXes do
if p.NumGroupPar = grp then
yield p.Num, p.Name]
Here is my sequence but the problem is it returns the list of tuples, I can't access single tuple element like
let str = "hello" + x.[1]
and that is the trouble.
how can I realize this functionary ?
To access the second element of a 2-tuple you can either use snd or pattern matching. So if tup is a 2-tuple, where the second element of tup is a string, you can either do:
let str = "hello" + snd tup
or
let (a,b) = tup
let st = "hello" + b
Note that snd only works with 2-tuples, not tuples with more than two elements.
To give you one more alternative solution, you can just create a filtered sequence containing values of the original type by writing yield p:
let x = [ for p in db.ParamsActXes do
if p.NumGroupPar = grp then
yield p ]
And then just access the property you need:
let str = "hello" + x.[1].Name
This is probably a good idea if you're returning only several properties of the p value. The only reason for yielding tuples would be to hide something from the rest of the code or to create sequence that matches some function you use later.
(Also, I would avoid indexing into lists using x.[i], because this is inefficient - but maybe this is just for ilustration in the sample you posted. Use an array if you need index based access by wrapping sequence expression into [| ... |])
Just to throw one more possibility out there, if you are running the .NET 4.0 build of F# 2.0 you can perform a runtime cast from the F# tuple to the .NET 4.0 System.Tuple and then use the ItemX properties of the .NET 4.0 tuples to access the tuple element you need,
let x = (1, 1.2, "hello")
let y = ((box x) :?> System.Tuple<int, float, string>);;
y.Item3 //returns "hello"
However, I would never use that, instead opting for the pattern match extraction. (also, I've read places that the F# compiler may not always choose to represent its tuples as .NET 4.0 tuples, so there may be a possibility that the cast would fail).
Reading your comments in some of the other answers, I'm unsure why the pattern matching solution doesn't work for you. Perhaps you want to access the tuple item at a certain place within an expression? If so, the previous would certainly work:
let str = "hello" + ((box x.[1]) :?> System.Tuple<int,string>).Item2 //though might as well use snd and fst for length 2 F# tuples
but you can achieve the same ends using the pattern matching extraction technique too (again, assuming this is even what you're after):
let str = "hello" + (let (_,name) = x.[1] in name)
you can access individual tuple from the list of tuple using List.nth.
let first, second = List.nth x 0
first and second represents the individual element of the tuple.

Resources