Skip to content

Commit 7179648

Browse files
committed
Implement priority-overload layers with modules, similar to task, to solve #97 use overload resolution bug
1 parent c2aa3a0 commit 7179648

File tree

8 files changed

+51
-58
lines changed

8 files changed

+51
-58
lines changed

src/FSharp.Control.TaskSeq/AsyncExtensions.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
namespace FSharp.Control
22

3-
open FSharp.Control.TaskSeqBuilders
4-
53
[<AutoOpen>]
64
module AsyncExtensions =
75

src/FSharp.Control.TaskSeq/AsyncExtensions.fsi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ namespace FSharp.Control
22

33
[<AutoOpen>]
44
module AsyncExtensions =
5-
open FSharp.Control.TaskSeqBuilders
65

76
type AsyncBuilder with
87

src/FSharp.Control.TaskSeq/TaskExtensions.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ open System.Threading.Tasks
77
open Microsoft.FSharp.Core.CompilerServices
88
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
99

10-
open FSharp.Control.TaskSeqBuilders
11-
1210
#nowarn "57"
1311
#nowarn "1204"
1412
#nowarn "3513"

src/FSharp.Control.TaskSeq/TaskExtensions.fsi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace FSharp.Control
44

55
[<AutoOpen>]
66
module TaskExtensions =
7-
open FSharp.Control.TaskSeqBuilders
87

98
type TaskBuilder with
109

src/FSharp.Control.TaskSeq/TaskSeq.fs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ open System.Threading.Tasks
77
#nowarn "57"
88

99
module TaskSeq =
10-
// F# BUG: the following module is 'AutoOpen' and this isn't needed in the Tests project. Why do we need to open it?
11-
open FSharp.Control.TaskSeqBuilders
1210

1311
// Just for convenience
1412
module Internal = TaskSeqInternal

src/FSharp.Control.TaskSeq/TaskSeq.fsi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace FSharp.Control
55
module TaskSeq =
66
open System.Collections.Generic
77
open System.Threading.Tasks
8-
open FSharp.Control.TaskSeqBuilders
98

109
/// Initialize an empty taskSeq.
1110
val empty<'T> : taskSeq<'T>

src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace FSharp.Control.TaskSeqBuilders
1+
namespace FSharp.Control
22

33
open System.Diagnostics
44

@@ -47,13 +47,6 @@ module Internal = // cannot be marked with 'internal' scope
4747

4848
type taskSeq<'T> = IAsyncEnumerable<'T>
4949

50-
type IPriority1 =
51-
interface
52-
end
53-
54-
type IPriority2 =
55-
interface
56-
end
5750

5851
[<NoComparison; NoEquality>]
5952
type TaskSeqStateMachineData<'T>() =
@@ -489,15 +482,7 @@ type TaskSeqBuilder() =
489482
true)
490483
)
491484

492-
member inline this.Using
493-
(
494-
disp: #IDisposable,
495-
body: #IDisposable -> TaskSeqCode<'T>,
496-
?priority: IPriority2
497-
) : TaskSeqCode<'T> =
498-
499-
// FIXME: what about priority?
500-
ignore priority
485+
member inline this.Using(disp: #IDisposable, body: #IDisposable -> TaskSeqCode<'T>) : TaskSeqCode<'T> =
501486

502487
// A using statement is just a try/finally with the finally block disposing if non-null.
503488
this.TryFinally(
@@ -508,26 +493,6 @@ type TaskSeqBuilder() =
508493
disp.Dispose())
509494
)
510495

511-
member inline this.Using
512-
(
513-
disp: #IAsyncDisposable,
514-
body: #IAsyncDisposable -> TaskSeqCode<'T>,
515-
?priority: IPriority1
516-
) : TaskSeqCode<'T> =
517-
518-
// FIXME: what about priorities?
519-
ignore priority
520-
521-
// A using statement is just a try/finally with the finally block disposing if non-null.
522-
this.TryFinallyAsync(
523-
(fun sm -> (body disp).Invoke(&sm)),
524-
(fun () ->
525-
if not (isNull (box disp)) then
526-
disp.DisposeAsync().AsTask()
527-
else
528-
Task.CompletedTask)
529-
)
530-
531496
member inline this.For(sequence: seq<'TElement>, body: 'TElement -> TaskSeqCode<'T>) : TaskSeqCode<'T> =
532497
// A for loop is just a using statement on the sequence's enumerator...
533498
this.Using(
@@ -536,14 +501,6 @@ type TaskSeqBuilder() =
536501
(fun e -> this.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke(&sm))))
537502
)
538503

539-
member inline this.For(source: #IAsyncEnumerable<'TElement>, body: 'TElement -> TaskSeqCode<'T>) : TaskSeqCode<'T> =
540-
TaskSeqCode<'T>(fun sm ->
541-
this
542-
.Using(
543-
source.GetAsyncEnumerator(sm.Data.cancellationToken),
544-
(fun e -> this.WhileAsync((fun () -> e.MoveNextAsync()), (fun sm -> (body e.Current).Invoke(&sm))))
545-
)
546-
.Invoke(&sm))
547504

548505
member inline _.Yield(v: 'T) : TaskSeqCode<'T> =
549506
TaskSeqCode<'T>(fun sm ->
@@ -556,9 +513,6 @@ type TaskSeqBuilder() =
556513
sm.Data.awaiter <- null
557514
__stack_fin)
558515

559-
member inline this.YieldFrom(source: IAsyncEnumerable<'T>) : TaskSeqCode<'T> =
560-
this.For(source, (fun v -> this.Yield(v)))
561-
562516
member inline this.YieldFrom(source: seq<'T>) : TaskSeqCode<'T> = this.For(source, (fun v -> this.Yield(v)))
563517

564518
member inline _.Bind(task: Task<'TResult1>, continuation: ('TResult1 -> TaskSeqCode<'T>)) : TaskSeqCode<'T> =
@@ -610,3 +564,52 @@ type TaskSeqBuilder() =
610564
sm.Data.awaiter <- awaiter
611565
sm.Data.current <- ValueNone
612566
false)
567+
568+
//
569+
// These "modules of priority" allow for an indecisive F# to resolve
570+
// the proper overload if a single type implements more than one
571+
// interface. For instance, a type implementing 'IDisposable' and
572+
// 'IAsyncDisposable'.
573+
//
574+
// See for more info tasks.fs in F# Core.
575+
//
576+
// This section also includes the dependencies of such overloads
577+
// (like For depending on Using etc).
578+
//
579+
580+
[<AutoOpen>]
581+
module MediumPriority =
582+
type TaskSeqBuilder with
583+
584+
member inline this.Using
585+
(
586+
disp: #IAsyncDisposable,
587+
body: #IAsyncDisposable -> TaskSeqCode<'T>
588+
) : TaskSeqCode<'T> =
589+
590+
// A using statement is just a try/finally with the finally block disposing if non-null.
591+
this.TryFinallyAsync(
592+
(fun sm -> (body disp).Invoke(&sm)),
593+
(fun () ->
594+
if not (isNull (box disp)) then
595+
disp.DisposeAsync().AsTask()
596+
else
597+
Task.CompletedTask)
598+
)
599+
600+
member inline this.For
601+
(
602+
source: #IAsyncEnumerable<'TElement>,
603+
body: 'TElement -> TaskSeqCode<'T>
604+
) : TaskSeqCode<'T> =
605+
TaskSeqCode<'T>(fun sm ->
606+
this
607+
.Using(
608+
source.GetAsyncEnumerator(sm.Data.cancellationToken),
609+
(fun e ->
610+
this.WhileAsync((fun () -> e.MoveNextAsync()), (fun sm -> (body e.Current).Invoke(&sm))))
611+
)
612+
.Invoke(&sm))
613+
614+
member inline this.YieldFrom(source: IAsyncEnumerable<'T>) : TaskSeqCode<'T> =
615+
this.For(source, (fun v -> this.Yield(v)))

src/FSharp.Control.TaskSeq/TaskSeqInternal.fs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ open System
44
open System.Collections.Generic
55
open System.Threading
66
open System.Threading.Tasks
7-
open FSharp.Control.TaskSeqBuilders
87

98
[<AutoOpen>]
109
module ExtraTaskSeqOperators =

0 commit comments

Comments
 (0)