I'd like to augment
public static IObservable<TSource> Create<TSource>(
Func<IObserver<TSource>, Action> subscribe)
{...}
For use in F# so that rather than calling with a Function or Action I can just use standard F# types i.e IObserver -> (unit -> unit).
How can I accomplish this?
Edit:
Adding full example. Not sure why obsAction does not work.
open System
open System.Reactive
open System.Reactive.Disposables
open System.Reactive.Linq
type Observable with
static member Create(subscribe) =
Observable.Create(fun observer -> Action(subscribe observer))
let obsDispose (observer:IObserver<_>) =
let timer = new System.Timers.Timer()
timer.Interval <- 1000.00
let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
timer.Elapsed.AddHandler(handlerTick)
timer.Elapsed.AddHandler(handlerElapse)
timer.Start()
Disposable.Empty
let obsAction (observer:IObserver<_>) =
let timer = new System.Timers.Timer()
timer.Interval <- 1000.00
let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
timer.Elapsed.AddHandler(handlerTick)
timer.Elapsed.AddHandler(handlerElapse)
timer.Start()
let action() =
timer.Elapsed.RemoveHandler(handlerTick)
timer.Elapsed.RemoveHandler(handlerElapse)
timer.Dispose()
action
let obsOtherAction (observer:IObserver<_>) =
let timer = new System.Timers.Timer()
timer.Interval <- 1000.00
let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
timer.Elapsed.AddHandler(handlerTick)
timer.Elapsed.AddHandler(handlerElapse)
timer.Start()
new System.Action( fun () ->
timer.Elapsed.RemoveHandler(handlerTick)
timer.Elapsed.RemoveHandler(handlerElapse)
timer.Dispose())
let worksNeverStops = obsDispose |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let actionWorks = obsOtherAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let doesNotWork = obsAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
The problem you're facing is an FP gotcha.
In,
static member Create(subscribe) =
Observable.Create(fun observer -> Action(subscribe observer))
the type of subscribe is IObserver<_> -> unit -> unit.
Now there's a subtle difference between IObserver<_> -> unit -> unit
and IObserver<_> -> Action where Action : unit -> unit. The difference is that the former is curried, and the latter isn't.
When an observer subscribes, subscribe observer returns a method in to which () can be applied to get unit - your subscribe method will never actually be called until the last () is applied - which won't be until it un-subscribes by which point it will already be detached.
You can get over it by forcing it to not be curried:
let action() = ... | let action = (subscribe observer)
Action(action)
Further:
If you check the IL, the equivalent VB (function refs are more clearer in VB) versions for the Invoke for the FastFunc generated for
static member Create(subscribe) =
Observable.Create(fun observer -> Action(subscribe observer))
is:
Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
Return New Action(AddressOf New Observable-Create-Static#27-1(Of a)(Me.subscribe, arg).Invoke)
End Function
and for:
static member Create(subscribe) =
Observable.Create(fun observer ->
let action = subscribe observer
Action(action))
is:
Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
Return New Action(AddressOf New Observable-Create-Static#28-1(Me.subscribe.Invoke(arg)).Invoke)
End Function
AddressOf New Closure(Me.subscribe, arg).Invoke -> The subscribe function won't get called until the dispose action is called.
AddressOf New Closure(Me.subscribe.Invoke(arg)).Invoke -> The subscribe function actually gets called and the resulting action is returned as expected.
I hope it is now clear why the second case works, and not the first.
Related
How can I achieve something like this in a clean way?
let's imagine this simple code:
let a () = checkSomeStuff (); None
let b () = do Something (); Some "thing"
let c () = checkSomethingElse (); None
"getOne" {
do! a()
do! b()
do! c()
}
and it would return the first "Some".
I could achieve this exact behavior by using Result where I'd return the value through an Error and continue through with Ok, but that is not readable / nice:
let a () = checkSomeStuff (); Ok ()
let b () = do Something (); Error "thing"
let c () = checkSomethingElse (); Ok ()
result {
do! a()
do! b()
do! c()
}
this would work, but I'm looking to achieve that without mis-using the Result type. Can it be done with the existing expressions?
You don't need a computation expression for this. F# has a built-in function called Seq.tryPick that applies a given function to successive elements of a sequence, returning the first Some result, if any. You can use tryPick to define getOne like this:
let getOne fs =
fs |> Seq.tryPick (fun f -> f ())
Trying it with your example:
let a () = checkSomeStuff ();
let b () = Something ();
let c () = checkSomethingElse ();
let x = getOne [ a; b; c ]
printfn "%A" x // Some "thing"
Some time ago, I wrote a post about imperative computation expression builder that does something along those lines. You can represent computations as option-returning functions:
type Imperative<'T> = unit -> option<'T>
In the computation builder, the main thing is the Combine operation that represents sequencing of operations, but you need a few others to make it work:
type ImperativeBuilder() =
member x.ReturnFrom(v) = v
member x.Return(v) = (fun () -> Some(v))
member x.Zero() = (fun () -> None)
member x.Delay(f:unit -> Imperative<_>) =
(fun () -> f()())
member x.Combine(a, b) = (fun () ->
match a() with
| Some(v) -> Some(v)
| _ -> b() )
let imperative = new ImperativeBuilder()
You can then reimplement your example - to return a value, you just use return, but you need to combine individual operations using return!, because the builder does not support do!:
let a () = imperative { printfn "one" }
let b () : Imperative<string> = imperative { return "result" }
let c () = imperative { printfn "two" }
let f = imperative {
return! a()
return! b()
return! c()
}
f()
You could create a function that does what you want. But you have to think throughout what you want to do.
So, your logic is.
You execute a function that returns an option
Then you check that option. if it is None you execute another function, if it is Some you return the value.
A function like these could look like this:
let getSome f opt =
match opt with
| None -> f ()
| Some x -> Some x
With such a function, you then could write. ***
let x =
checkSomeStuff ()
|> getSome (fun _ -> Something () )
|> getSome checkSomethingElse
But then i think, hmmm.... isn't there a better name for getSome? In some way i want to say:
Execute some code and check if it is Some, or else pick the next thing.
With this in mind, i think. hmm.... isn't there already a Option.orElse? And yes! There is! There is also a Option.orElseWith function, that fits your need even better. So now, you can write.
let y =
checkSomeStuff ()
|> Option.orElseWith (fun _ -> Something () )
|> Option.orElseWith checkSomethingElse
If you have functions with side-effects, then you should use Option.orElseWith, otherwise, you can just sue Option.orElse
***: I assume you have the following function defined
let checkSomeStuff () =
None
let Something () =
Some "thing"
let checkSomethingElse () =
None
When I'm working in F# Interactive, I often want to make changes to an event handler. Simply calling the Subscribe or Add or AddHandler functions on an event causes the old event to continue being called, which is rarely the intention.
One solution is to use the IDisposable that it returns, but that requires tracking the IDisposables in your own code, which is cumbersome for exploratory tasks.
I've tried making a Dictionary<IEvent,IDisposable> to call Dispose() when the same event is subscribed to again:
let events = Dictionary<obj, IDisposable>()
let subonce (e:IEvent<'h,'e>) (handler: 'e -> unit) =
if events.ContainsKey e then
events.[e].Dispose()
events.Remove e |> ignore
let d = e.Subscribe handler
events.Add (e,d) |> ignore
let w = Window()
w.Show()
//Running this line in FSI a second time onward should Dispose() the previous subscription
subonce w.MouseUp (fun e -> printfn "%A" <| e.GetPosition(w))
Unfortunately, as it turns out, F# generates a new IEvent instance, so naively using = or obj.Equals doesn't cut it.
> w.MouseUp;;
val it : IEvent<Input.MouseButtonEventHandler,Input.MouseButtonEventArgs> =
<published event> {addHandler = <fun:it#5-70>;
createHandler = <fun:it#5-72>;
removeHandler = <fun:it#5-71>;}
> w.MouseUp;;
val it : IEvent<Input.MouseButtonEventHandler,Input.MouseButtonEventArgs> =
<published event> {addHandler = <fun:it#6-74>; //note that these functions are of a different anonymous instance
createHandler = <fun:it#6-76>;
removeHandler = <fun:it#6-75>;}
Are there any properties or fields I can find within an IEvent that would identify it against other instances of the owner and against different events in that owner?
Not exactly an answer to the question, but I can't think of many other scenarios in which you'd need to identify an event instance, so maybe this is good enough:
type OneHandler<'e> = { mutable h : 'e -> unit }
let onehandler (e:IEvent<'h,'e>) =
let h = { h = fun _ -> () }
e.Subscribe(fun e -> h.h e) |> ignore
h
let w = Window()
let wmouseup = onehandler w.MouseUp
wmouseup.h <- (fun e -> printfn "%A" <| e.GetPosition(w))
This way, by evaluating just the assignment to wmouseup.h, we can change the event handler without having to restart the w or juggle IDisposable or Handler objects.
I'm having a bit of trouble with the following FSharp/F# code:
module File1
let api a =
printf ("VALUE = %A") a
let router ops =
[|
api (ops (fun (list, _) -> list()))
api (ops (fun (_, get) -> get 1))
|]
let withContext ops handler =
let context = "CONTEXT"
handler (ops context)
let operations context =
printf ("CONTEXT = %s") context
let list () = [|1;2;3|]
let get id = "Test"
(list, get)
let setup() =
let ops = withContext operations
router ops
Results in the following error
Results in the following compation error
Error 1 Type mismatch. Expecting a
((unit -> int []) * (int -> int []) -> int []) -> 'a
but given a
((unit -> int []) * (int -> string) -> 'b) -> 'b
The type 'int []' does not match the type 'string'
I know the problem is that ops function has been bound to return a int[] but I want to be able to also return a string.
I think I'm missing a trick with some generic declarations but after hours of moving code around I can’t seem to work it out.
(I've simplified the code to highlight my problem)
The error is because ops needs to have a return type of its handler resolved at compilation, and you want to return different types base on some run-time logic.
It is basically an equivalent of:
let fun1 switch arg2 arg3 =
if switch then
arg2
else
arg3
and you want to run it this way:
fun1 true 1 "string"
Of course, arg2 and arg3 need to have the same type, so it won't work
What you can do is to run "api" function on a handler result, before returning it (so it will always the same type - unit).
let router ops =
[|
ops (fun (list, _) -> api <| list()))
ops (fun (_, get) -> api <| get 1))
|]
Alternatively, you could return objects of discriminated union type (then you will need some more logic in api function).
(Technically, you could also return obj).
Bonus
You don't need the array of units to be returned in a router function, returning one unit is just fine:
let router ops =
ops (fun (list, _) -> api <| list()))
ops (fun (_, get) -> api <| get 1))
In this way, setup function will also return unit and you will be able to run it without a need to run ignore on the result to get rid of This expression should have type 'unit', but has type 'unit[]' warning.
Your code is hard for me to understand, but I think the basic issue is that you want withContext to have a "rank 2" type (so that the universal quantification of the type variable 'b can happen after the application of the first argument). In F#, this can be accomplished by creating a new type with a generic method and using that:
let api a =
printf ("VALUE = %A") a
type Handler<'a> = abstract Handle<'b> : f:('a->'b) -> 'b
let router (ops:Handler<_>) =
[|
api (ops.Handle (fun (list, _) -> list()))
api (ops.Handle (fun (_, get) -> get 1))
|]
let withContext ops =
let context = "CONTEXT"
{ new Handler<_> with member __.Handle f = f (ops context) }
let operations context =
printf ("CONTEXT = %s") context
let list () = [|1;2;3|]
let get id = "Test"
(list, get)
let setup() =
let ops = withContext operations
router ops
I have an F# 3.0 agent wrapped in a class:
type AgentWrapper() =
let myAgent = Agent.Start(fun inbox ->
let rec loop (state: int) =
async {
let! (replyChannel: AsyncReplyChannel<int>) = inbox.Receive()
let newState = state + 1
replyChannel.Reply newState
return! loop newState
}
loop 0 )
member private this.agent = myAgent
member this.Send () =
this.agent.PostAndReply (fun replyChannel -> replyChannel)
When I send messages to it as follows:
let f = new AgentWrapper ()
f.Send () |> printf "Reply: %d\n"
f.Send () |> printf "Reply: %d\n"
f.Send () |> printf "Reply: %d\n"
I get the expected responses:
Reply: 1
Reply: 2
Reply: 3
However, if I remove the let binding for the agent and directly assign it to the this.agent property:
type AgentWrapper() =
member private this.agent = Agent.Start(fun inbox ->
let rec loop (state: int) =
async {
let! (replyChannel: AsyncReplyChannel<int>) = inbox.Receive()
let newState = state + 1
replyChannel.Reply newState
return! loop newState
}
loop 0 )
member this.Send () =
this.agent.PostAndReply (fun replyChannel -> replyChannel)
I then get the responses:
Reply: 1
Reply: 1
Reply: 1
I've been staring at this for hours and I can't understand why the agent is getting re-initialised every time I call AgentWrapper.Send. It feels like this.agent is getting reassigned every time I call it (i.e. acting like a method, not a property). What am I missing?
It feels like this.agent is getting reassigned every time I call it
(i.e. acting like a method, not a property). What am I missing?
This is exactly what happens, and is documented in the spec (relevant part from 18.13.1 follows)
Static and instance property members are evaluated every time the
member is invoked. For example, in the following, the body of the
member is evaluated each time C.Time is evaluated:
type C () =
static member Time = System.DateTime.Now
This is analgous to your situation
I have the following code snippet using the reactive extensions:
let value : 't = ...
Observable.Create<'t>(fun observer ->
let subject = new BehaviorSubject<'t>(value)
let d0 = subject.Subscribe(observer)
let d1 = observable.Subscribe(subject)
new CompositeDisposable(d0, d1) :> IDisposable
)
This works. However if I drop the upcast to IDisposable then the code fails
to compile, citing ambiguous overloads. However CompositeDisposable is an
IDisposable. Why is the type inference engine failing to resolve this? Note I use this pattern almost all the time in C# returning CompositeDisposable from Observable.Create without having to upcast.
As #kvb said, functions don't support variance so upcast is required for interfaces and subclasses.
Here is a small example demonstrating the behavior with subclasses:
type A() =
member x.A = "A"
type B() =
inherit A()
member x.B = "B"
let f (g: _ -> A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails
If function f is written by you, adding type constraints could help:
// This works for interface as well
let f (g: _ -> #A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works
Otherwise, you have to do a litle upcast as your example described.
EDIT: Since F# 6.0, auto-upcasting of interfaces and subclasses is now supported by default.