Comments (5)
It is the wonders of overloading. The job builder has two overloads for For and apparently the array overload gets selected by default. Can you give a type for the xs parameter?
from hopac.
Hmmm, it clearly wouldn't have been sound to give overloading precedence based on the order it was defined in the builder but sure would've been convenient.
I've been trying to define a combined builder for Validation+Reader in the hope of supporting:
'context -> 'a
'context -> Choice<'a, 'b>
Choice<'a, 'b>
Naturally I could only support both 'context -> Choice<'a, 'b>
and Choice<'a, 'b>
from hopac.
Could also try quasi-static overloading:
let length<'E,'T when 'T :> seq<'E>> : 'T -> int =
if typeof<'T>.IsArray then
Array.length<'E> :> obj :?> _
else
fun xs -> Seq.length xs
Code along these lines can be arranged that selection happens O(1)
at application startup.
from hopac.
This is a surprisingly complex issue. Normally I would think that this is not a
very critical issue in any way. But... I think that issues like this arise from
mixing subtyping and overloading occasionally, so I've spent some time looking
at the "Method Application Resolution" rules of F# to see if there would be way
to guide the resolution process usefully.
Unfortunately, I don't see how to do that in this case. This is not to say that
it would be impossible. I considered adding optional arguments to "poison"
overloads, but that effectively eliminates those overloads completely. I also
considered using extension methods. There is a special rule that the most
recently opened extension methods are preferred, but unfortunately that doesn't
seem to apply in this case. I don't immediately see other rules that might help
in this caseโat least not without substantial trickery, which I'd prefer
to avoid.
If I understand the overload resolution specification correctly, the reason F#
chooses the array overload is that it has a more specific type than the seq
overload. This is basically sound.
If we'd add another overload, say for lists, which is actually something I've
had in mind, but have not yet implemented, the resolution process would fail and
report an error for the example code. To fix the code to compile, one could
simply add the type constraint (xs: seq<_>)
. Because adding such overloads is
something I've already considered doing, but haven't yet had the time, and
because this would merely have the effect of requiring user code to be more
explicit about types and would not impede compiler optimizations like inlining,
I find this to be a reasonable solution.
The suggested quasi static approach can be quite nice in certain contexts. I've
used similar techniques in cases where I've effectively wanted a mapping from
types to values.
The quasi static approach has the following properties:
- The JIT will generate a bit of static data for every type that the quasi
static thing is used with. In this case for every type
CollectionType<ElementType>
. - With initializer code, the JIT will also generate a bit of code at every
access to the quasi static data to check whether the initialization code has
already been run or not and to run the initialization code if not. Without
initializer code, in this case, we would need to write an equivalent
initialization check, because the default uninitialized value will not help. - In this case we also need to invoke functionality via that static data, so
there is a need to perform a virtual method call. Aside from the cost of the
virtual call itself, this will have the effect of preventing F# from
performing inlining.
In this particular case inlining is not used, but since For is given a closure
as an argument, there is a possibility that inlining performed by F# could give
significant benefits. In this case we also don't necessarily want a full
mapping from all CollectionType<ElementType>
types to a specialized for loop.
We only want to choose between two (or few) generic specilizations for different
collections.
If we ignore the potential for inlining and many more specialized versions of
For would be added, then the quasi static approach would likely become faster
than a run-time type test, but for choosing between seq and array
specialization, a run-time type test (i.e. having just a single seq version of
For that checks if the given sequence is an array) is likely to be faster (type
tests seem to have a cost similar to the cost a virtual function call).
I don't really like either way of specializing the behavior of For in this case
(run time tests or the quasi static method).
For best performance, I'd choose the option of adding another overload, which
will require used code to be explicit about the types.
The simplest thing to do would be to simply remove the array overload. This
would require user code to very explicitly use array specific code when desired
as an optimization.
So, I'm basically leaning towards either removing the array overload or adding a
list overload. Both approaches require user code to be more specific, but in
different ways.
from hopac.
Indeed. The simplest thing that works, is drop this overload and do:
Job.forArray arr (fun item -> job { .. })
from hopac.
Related Issues (20)
- Add Azure DevOps build HOT 2
- Problems with network stream HOT 9
- Handling exceptions HOT 9
- Stack Overflow in Alt.choose HOT 3
- Fibonacci benchmark fails with Stack Overflow on NET Core, but not on Framework HOT 4
- Production Ready? HOT 5
- IAsyncEnumerable<T> interop HOT 1
- How to convert to task? HOT 6
- ValueTask<T> interop HOT 1
- How to get the build working on Windows? HOT 2
- Stack overflow with recursive job HOT 5
- Is this project dead? HOT 1
- Why do these two code snippets result in different behavior HOT 1
- FSharp.Core 5.0 support HOT 15
- Why does the left side not uncommit after the right side has been chosen when using Alt.prepare? HOT 8
- How can uncaught exception errors be redirected?
- BadImageFormatException HOT 6
- How to conCollect but stop on first exception? HOT 8
- System.Diagnostics.Activity doesn't flow properly with Hopac, resulting in incorrect telemetry correlation
- Example of paranoid function?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hopac.