In F#, how to list the PrintQueues from the PrintQueueCollection? - printing

(Newbie question).
I am attempting to list out the PrintQueues from the Microsoft PrintQueColletion in F#. Something like this:
let GetPrinters :List<PrintQueue> =
let localPrintServer = new PrintServer()
let printQueues = localPrintServer.GetPrintQueues [|EnumeratedPrintQueueTypes.Local; EnumeratedPrintQueueTypes.Connections|]
let printerList = printQueues |> ????
printerList
But I can't get how to turn the PrintQueueCollection into a list of PrintQueue.
Any suggestions will be most appreciated.
TIA
Hint: in C#, this is:
public static List<PrintQueue> GetPrinters()
{
PrintServer localPrintServer = new PrintServer();
PrintQueueCollection printQueues = localPrintServer.GetPrintQueues(new[] {
EnumeratedPrintQueueTypes.Local,
EnumeratedPrintQueueTypes.Connections });
var printerList = (from printer in printQueues
select printer)
.ToList();
return printerList;
}

UPDATE: See improved answer below this one.
This should do it:
let printerList =
printQueues
|> Seq.cast<PrintQueue>
|> Seq.toList
The trick here is that if you want printQueues to behave like an IEnumerable<PrintQueue>, you have to explicitly wrap it. This is what Seq.cast does.
(Side note: This is just one reason why having weakly-typed FooCollection classes instead of using built-in strongly-typed collections is a bad idea in general. Such is the legacy of old C# code.)

My first answer isn't technically correct, so I want to fix it here to make sure you see the update. It turns out that you don't need an explicit cast in this case, so the following simpler code will also work:
let printerList =
printQueues
|> Seq.toList
The rest of my explanation in the previous answer is correct for handling weakly-typed collections, but PrintQueueCollection is actually a strongly-typed IEnumerable<PrintQueue>, so it works just fine with the Seq module as it is. Sorry about that.

Related

How to use FSharpPlus.Lens to specify the index of a list?

The sample code of the documentation defines _pageNumber using List._item, but I can't seem to find an example of its use.
I tried the following code but it gave an error.
view (Book._pageNumber 1) rayuela // error
How would it be used?
I'm seeing the same thing:
No overloads match for method 'Zero'".
The problem is caused by the _Some lens, which doesn't work with record types, because they don't have a default (i.e. "zero") value:
let inline _pageNumberOpt i b =
_pages << List._item i <| b
let pageOpt = view (_pageNumberOpt 1) rayuela // this is fine
let page = view _Some pageOpt // this doesn't work, because the input is an Option<Page>
let x = view _Some (Some 1) // this works, because the input is an Option<int>
This appears to be a limitation in FSharpPlus that wasn't accounted for in the documentation. If you want to work around the problem, you can define Page.Zero yourself, and then the example will compile:
type Page =
{ Contents: string }
static member Zero = { Contents = "" }
let page = view (Book._pageNumber 1) rayuela
printfn $"{page}" // output is: { Contents = "The End" }
let noPage = view (Book._pageNumber 5) rayuela
printfn $"{noPage}" // output is: { Contents = "" }
Page.Zero will only be called if you ask for a page that doesn't exist, but it needs to be there for the compiler in any case.
(FWIW, in my experience, FSharpPlus is a very, very delicate beast. It's an interesting experiment, but it breaks easily. And when it breaks, the compiler errors are mind-boggling.)
Brian's answer is very accurate from the technical viewpoint but conceptually misses the most important point: you're "viewing" a partial lens (also called prism), instead of "previewing" it. This is not a limitation of F#+, this is just how lens behaves.
Some background: Prisms or partial lenses are like a lens that can fail, so in principle you can't use the view operation on them because it's an operation that always succeed, or better said doesn't consider a failure, you should use the preview operation which returns an option.
The composition rules state that the result of composing:
a lens with a lens is a lens
a lens with a prism (or the other way around) is a prism
a prism with a prism is a prism
This is, as soon as there is a prism in the composition chain the result will be a prism.
In our case we have _pages << List._item i << _Some which are lens composed with lens composed with _Some which is a prism, so _pageNumber i will be a prism.
Now, what happens if you use view for a prism? The zero value represents a failure, for instance the zero value of an option is None, but here there is no zero value specified.
Brian is right in that the error message is misleading, a better error would be "don't use view over a prism", but instead what happen is to try to get a naked value (not inside an option) which can represent failures with zero.
TL; DR
use instead:
preview (Book._pageNumber 1) rayuela // Some { Contents = "The End" }
Someone should send a PR to add that line to the docs.

Documentdb ReadDocumentAsync doesn't work

I have the following F# code attempting to get a user document from my documentdb database and it doesn't work. Is anyone else experiencing problems using the ReadDocumentAsync method? I am able to successfully to query my user documents with the CreateDocumentQuery method. Any help is greatly appreciated. I use my database and collection ids in place of the empty strings in the code snippet
let getUserDatabaseModel (documentClient : DocumentClient) originiatorId =
async {
let databaseId = ""
let collectionId = ""
let documentUri = UriFactory.CreateDocumentUri(databaseId, collectionId, originiatorId)
let! userDatabaseModel =
documentClient.ReadDocumentAsync(documentUri)
|> Async.AwaitTask
return userDatabaseModel
}
|> Async.RunSynchronously
Update
If I use the _rid instead of the id I get the data back. To clarify the ReadDocumentAsync seems to work using the _rid but throws the error below when using the id.
mscorlib: Exception has been thrown by the target of an invocation.
FSharp.Core: One or more errors occurred. Microsoft.Azure.Documents.Client:
The value 'left blank intentionally' specified for
query '$resolveFor' is invalid
I posted a while back on the documentdb github issues page, problems I was having with ReplaceDocumentAsync.
https://github.com/Azure/azure-documentdb-dotnet/issues/113
I wasn't too concerned about the fix because there was UpsertDocumentAsync. This issue seems to be related, or maybe their relation is just me! not being able to figure out what I'm doing wrong.
CreateDocumentUri needs consistent ids, either all ids or all _rids for the database, collection, and document

Slick 3.0 Howto change the return type of a join to a more useful value

currently I try to create some Join Queries on slick, however like the nature of the Join it will have the result of Seq(ObjectA1, ObjectB) and if the right hand object has many left hand objects it will look like that:
Seq[
(ObjectA, Object1),
(ObjectA, Object2),
(ObjectA, Object3),
(ObjectB, Object4),
(ObjectB, Object5)
]
How could I transform these values to have a more flat structure like that:
Seq[(ObjectA, Seq[Object1, Object2, Object3]), (ObjectB, Seq[Object4, Object5])]
Is there any good way to do that?
Oh and here is my Code:
def testInnerJoin(id: Rep[Long]) = for {
(td, t) <- termsData joinRight terms on (_.termsId === _.id) if t.id === id
} yield (t, td)
val compiledJoin = Compiled(testInnerJoin _)
def queryThat = {
db.run(compiledJoin(2L).result)
}
Without knowing what's good or bad I would just do it like that:
db.run(compiledJoin(2L).result).map(data=> data.groupBy(_._1).mapValues(_.map(_._2)))
however doesn't look to efficient, since the most computation is running inside scala, so any suggestions?

Deedle - create empty list and series

I am new to F#, looking at it as an alternative to Matlab.
In reference to this question, how can I create an empty Serie and an empty Frame.
If I did not just miss it, why an empty Serie or Frame has not been designed in the library,
something like list.empty ?
Adding Frame.empty and Series.empty is a great suggestion. I think these should be in the library and I'm adding an issue to GitHub to make sure they get added.
In the meantime, you should be able to use something like this:
let empty : Series<int, float> = series []
let empty : Frame<int, string> = frame []
Note that I had to add type annotations - from my code snippet, the compiler cannot figure out what is the type of keys and values, so I had to explicitly specify that (but if you use the values as arguments to other functions, then this should not be needed).
The second line does not actually work in the current version, because of a bug (oops!) so you can use Frame.ofRows instead, which works fine:
let frame : Frame<int, string> = Frame.ofRows []
EDIT: The bug is now fixed in version 0.9.11-beta

Problem creating an Entity object/queryable from the result of a LINQ join in MVC

I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);

Resources