Can't compare functions in f# for event subscription guard - events

I'm trying to stop an event from subscribing to an event twice with this:
let ex = new Event<int>()
let lst = new ResizeArray<obj>()
let subscribe f =
if (lst.Contains f) then // <- doesn't work, can't compare functions
failwith ("subscribed twice!!")
else
lst.Add(f)
let obs = ex.Publish :> System.IObservable<_>
obs |> Observable.subscribe f
Unfortunately, it doesn't work. For example
let foo x = printfn "%d" x
subscribe foo
subscribe foo
ex.Trigger 42 // Produces 42 42
Looks like we can't compare functions in F#.
if (foo = foo) then () // won't compile
(foo :>obj) = (foo :> obj) // = false
Is there a way to compare functions or is there another way to stop multiple subscriptions on Events/IObservables?

Related

Getting a random number in a function in OCAML OR Telling compiler to evaluate function each time

I'm new to OCAML and was playing around with putting a marker on a random 5X5 square. I've written the example program below. "silly_method1" works but notice that it takes an argument. I don't really have argument to pass in for what I want. I'm just asking for a random number to create my robot on a particular square:
let create = {x = ( Random.int 4); y=3; face = North}
However, I get the same location each time. This makes sense to me... sort of. I'm assuming that the way I've set it up, "create" is basically a constant. It's evaluated once and that's it! I've fixed it below in silly_method2 but look how ugly it is!
let silly_method2 _ = (Random.int 10)
Every time I have to call it, I have to pass in an argument even though I'm not really using it.
What is the correct way to do this? There must be some way to have a function that takes no arguments and passes back a random number (or random tuple, etc.)
And possibly related... Is there a way to tell OCaml not to evaluate the function once and save the result but rather recalculate the answer each time?
Thank you for your patience with me!
Dave
let _ = Random.self_init()
let silly_method1 x = x + (Random.int 10)
let silly_method2 _ = (Random.int 10)
let report1 x = (print_newline(); print_string("report1 begin: "); print_int (silly_method1 x); print_string("report1 end"); print_newline(); )
let report2 y = (print_newline(); print_string("report2 begin: "); print_int(silly_method2 y ); print_string("report2 end"); print_newline(); )
let _ = report1 3
let _ = report1 3
let _ = report1 3
let _ = report2 3
let _ = report2 3
let _ = report2 3
The idiomatic way to define a function in OCaml that doesn't take an argument is to have the argument be (), which is a value (the only value) of type unit:
# let f () = Random.int 10;;
val f : unit -> int = <fun>
# f ();;
- : int = 5
# f ();;
- : int = 2
OCaml doesn't save function results for later re-use. If you want this behavior you have to ask for it explicitly using lazy.

How to abstract non-linear list iteration schemes into a re-usable algorithm?

On the odd chance, that someone has a brilliant idea...
I am not sure if there is a good way to generalize that.
EDIT: I think it might be nice to explain exactly what the inputs and outputs are. The code below is only how I approached the solution.
Inputs: data, recipe
data: set of string, string list here also called "set of named lists"
recipe: list of commands
Command Print (literal|list reference)
Adds the literal to the output or if it is a list reference, it adds the head of the referenced list to the output.
Command While (list reference)
when referenced list not empty --> next command
when referenced list empty --> skip entries in recipe list past the matching Wend.
Command Wend (list reference)
replace referenced list with tail (reference list)
when referenced list is empty, next command
when referenced list is not empty, next command is the matching while above.
Outputs: string list
The best answer is the implementation of that which is shortest and which allows to re-use that algorithm in new contexts.
This is not just a programming problem for the fun of it, btw. It is basically what happens if you try to implement data driven text templating.
The code below is my attempt to solve this problem.
The first code snippet is a non-generalized solution.
The second code snippet is an attempt to isolate the algorithm.
If you play with the code, simply paste the second snippet below the first snippet and both versions are working.
The whole topic is about understanding better how to separate the iteration algorithm from the rest of the code and then to simply apply it, in contrast of having all the other code within.
Would it not be great, if there was a way to abstract the way the statements are being processed and the looping of the while/wend, such,
that it can be reused in my main code, just as I keep re-using other "iteration schemes", such as List.map?
The commonalities between my main code and this study are:
An evolving "environment" which is threaded through all steps of the computation.
Collections, which need to be iterated in a well-formed nested manner. (Malformed would be: while x while y wend x wend y)
A series of "execution steps" form the body of each of those "while wend" loops.
Done in a "pure" manner. As you will note, nothing is mutable in the study. Want to keep it like that.
Each "While" introduces a new scope (as for binding values), which is discarded again, once the while loop is done.
So, I am looking for something like:
run: CommandClassifier -> commandExecutor -> Command list -> EnvType -> EnvType
where
CommandClassifier could be a function of the form Command -> NORMAL|LOOP_START|LOOP_END
and commandexecutor: Command -> EnvType -> EnvType
Of course, nesting of those while-blocks would not be limited to 2 (just tried to keep the testProgram() small).
SideNote: the "commands list" is an AST from a preceding parser run, but that should not really matter.
type MiniLanguage =
| Print of string
| While of string
| Wend of string
let testProgram =
[ Print("Hello, I am your Mini Language program")
While("names")
Print("<names>")
While("pets")
Print("<pets>")
Wend("pets")
Print("Done with pets.")
Wend("names")
Print("Done with names.")
]
type MiniEnvironment = { Bindings : Map<string,string>; Collections : Map<string, string list> }
let init collections =
{ Bindings = Map.empty; Collections = Map.ofList collections}
let bind n v env =
let newBindings =
env.Bindings
|> Map.remove n
|> Map.add n v
{ env with Bindings = newBindings; }
let unbind n env =
{ env with Bindings = Map.remove n env.Bindings; }
let bindingValue n env =
if env.Bindings.ContainsKey n then
Some(env.Bindings.Item n)
else
None
let consumeFirstFromCollection n env =
if env.Collections.ContainsKey n then
let coll = env.Collections.Item n
match coll with
| [] -> env |> unbind n
| _ ->
let first = coll.Head
let newCollections =
env.Collections
|> Map.remove n
|> Map.add n coll.Tail
{ env with Collections = newCollections }
|> bind n first
else failwith ("Unknown collection: " + n)
// All do functions take env - the execution environment - as last argument.
// All do functions return (a new) env as single return parameter.
let rec doPrint (s : string) env =
if s.StartsWith("<") && s.EndsWith(">") then
match bindingValue (s.Substring (1, s.Length - 2 )) env with
| Some(v) -> v
| _ -> s
else s
|> printfn "%s"
env
let rec skipPastWend name code =
match code with
| (Wend(cl) :: rest) when cl = name -> rest
| [] -> failwith "No Wend found!"
| (_ :: rest) -> skipPastWend name rest
let rec doWhileX name code env =
match code with
| (Print(s) :: rest) -> env |> (doPrint s) |> doWhileX name rest
| (While(cn) :: rest) -> env |> doWhile cn rest |> ignore; env |> doWhileX name (skipPastWend cn rest)
| (Wend(cn) :: rest) when cn = name -> env
| [] -> failwith ("While without Wend for: " + name)
| _ -> failwith ("nested while refering to same collection!")
and doWhile name code env =
let e0 = env |> consumeFirstFromCollection name
match bindingValue name e0 with
| Some(s) ->
e0 |> doWhileX name code |> doWhile name code
| None -> env
let rec run (program : MiniLanguage list) env =
match program with
| (Print(s) :: rest) -> env |> (doPrint s) |> run rest
| (While(cn) :: rest) ->
env
|> doWhile cn rest |> ignore
env |> run (skipPastWend cn program)
| (Wend(cn) :: rest) -> failwith "wend found in run()"
| [] -> env
let test() =
init [ "names", ["name1"; "name2"; "name3"; ]; "pets", ["pet1"; "pet2"] ]
|> run testProgram
|> printfn "%A"
(*
Running test() yields:
Hello, I am your Mini Language program
name1
pet1
pet2
Done with pets.
name2
pet1
pet2
Done with pets.
name3
pet1
pet2
Done with pets.
Done with names.
{Bindings = map [];
Collections =
map [("names", ["name1"; "name2"; "name3"]); ("pets", ["pet1"; "pet2"])];}
*)
Here my first version of isolating the algorithm. The number of callbacks is not entirely pretty. Can anyone come up with something simpler?
// The only function I had to "modify" to work with new "generalized" algorithm.
let consumeFirstFromCollection1 n env =
if env.Collections.ContainsKey n then
let coll = env.Collections.Item n
match coll with
| [] -> (env |> unbind n , false)
| _ ->
let first = coll.Head
let newCollections =
env.Collections
|> Map.remove n
|> Map.add n coll.Tail
({ env with Collections = newCollections }
|> bind n first , true)
else failwith ("Unknown collection: " + n)
type NamedList<'n,'t when 'n : comparison> = 'n * List<'t>
type Action<'a,'c> = 'c -> 'a -> 'a
type LoopPreparer<'a,'c> = 'c -> 'a -> 'a * bool
type CommandType = | RUN | BEGIN | END
type CommandClassifier<'c> = 'c -> CommandType
type Skipper<'c> = 'c -> List<'c> -> List<'c>
type InterpreterContext<'a,'c> =
{ classifier : CommandClassifier<'c>
executor : Action<'a,'c>
skipper : Skipper<'c>
prepareLoop : LoopPreparer<'a,'c>
isMatchingEnd : 'c -> 'c -> bool
}
let interpret (context : InterpreterContext<'a,'c>) (program : 'c list) (env : 'a) : 'a =
let rec loop front (code : 'c list) e =
let e0,hasData = e |> context.prepareLoop front
if hasData
then
e0
|> loop1 front (code)
|> loop front (code)
else e
and loop1 front code e =
match code with
| x :: more when (context.classifier x) = RUN ->
//printfn "RUN %A" x
e |> context.executor x |> loop1 front more
| x :: more when (context.classifier x) = BEGIN ->
//printfn "BEGIN %A" x
e |> loop x more |> ignore
e |> loop1 front (context.skipper x more)
| x :: more when (((context.classifier x) = END) && (context.isMatchingEnd front x)) -> /// && (context.isMatchingEnd front x)
//printfn "END %A" x
e
| [] -> failwith "No END."
| _ -> failwith "TODO: Not sure which case this is. But it is not a legal one!"
let rec interpr code e =
match code with
| [] -> e
| (first :: rest) ->
match context.classifier first with
| RUN -> env |> context.executor first |> interpr rest
| BEGIN ->
e |> loop first rest |> ignore
e |> interpr (context.skipper first rest)
| END -> failwith "END without BEGIN."
interpr program env
let test1() =
let context : InterpreterContext<MiniEnvironment,MiniLanguage> =
{ classifier = fun c-> match c with | MiniLanguage.Print(_) -> RUN | MiniLanguage.While(_) -> BEGIN | MiniLanguage.Wend(_) -> END;
executor = fun c env -> match c with | Print(s) -> doPrint s env | _ -> failwith "Not a known command.";
skipper = fun c cl -> match c with | While(n) -> skipPastWend n cl | _ -> failwith "first arg of skipper SHALL be While!"
prepareLoop = fun c env -> match c with | While(n) -> (consumeFirstFromCollection1 n env) | _ -> failwith "first arg of skipper SHALL be While!"
isMatchingEnd = fun cwhile cx -> match cwhile,cx with | (While(n),Wend(p)) when n = p -> true | _ -> false
}
init [ "names", ["name1"; "name2"; "name3"; ]; "pets", ["pet1"; "pet2"] ]
|> interpret context testProgram
|> printfn "%A"

OCaml websocket "Invalid UTF8 data"

I am trying to build a loop with Lwt that will push a frame to a Websocket, wait for the response, print it to the screen, wait 60 seconds and then repeat the process again. I have been able to get something that compiles but I do not have it 100% right yet. The first time through the loop everything works fine, then every time after that I receive the error message "Invalid UTF8 data". I must have something wrong in my Lwt loop or in my understanding of Websocket protocols. My code:
#require "websocket";;
#require "lwt";;
#require "lwt.syntax";;
open Lwt
(* Set up the websocket uri address *)
let ws_addr = Uri.of_string "websocket_address"
(* Set up the websocket connection *)
let ws_conn = Websocket.open_connection ws_addr
(* Set up a frame *)
let ws_frame = Websocket.Frame.of_string "json_string_to_server"
(* push function *)
let push frame () =
ws_conn
>>= fun (_, ws_pushfun) ->
ws_pushfun (Some frame);
Lwt.return ()
(* get stream element and print to screen *)
let get_element () =
let print_reply (x : Websocket.Frame.t) =
let s = Websocket.Frame.content x in
Lwt_io.print s; Lwt_io.flush Lwt_io.stdout;
in
ws_conn
>>= fun(ws_stream, _) ->
Lwt_stream.next ws_stream
>>= print_reply
let rec main () =
Lwt_unix.sleep 60.0
>>= (push ws_frame)
>>= get_element
>>= main
Lwt_main.run(main ())
I'm not sure what particularly incorrect with your code. It even doesn't compiles on my system. It looks like you were experimenting with it in a top-level and created some strange context. I've rewritten your code in a somewhat more cleaner way. First of all I pass a connection to the function, so that it is more cleaner, what your functions do. Also it is not a good idea to wait for the same thread again and again. This is not how things are done is Lwt.
open Lwt
(* Set up the websocket uri address *)
let ws_addr = Uri.of_string "websocket_address"
(* Set up a frame *)
let ws_frame = Websocket.Frame.of_string "json_string_to_server"
(* push function *)
let push (_,push) frame =
push (Some frame);
return_unit
(* get stream element and print to screen *)
let get_element (stream,_) =
let print_reply (x : Websocket.Frame.t) =
let s = Websocket.Frame.content x in
Lwt_io.printlf "%s%!" s in
Lwt_stream.next stream
>>= print_reply
let rec main conn : unit t =
Lwt_unix.sleep 60.0
>>= fun () -> push conn ws_frame
>>= fun () -> get_element conn
>>= fun () -> main conn
let () = Lwt_main.run (
Websocket.open_connection ws_addr >>= main)

OCaml Websocket example

I am not sure how to fully use the OCaml Websocket library. I was hoping that somebody could help me out with a simple example. I am trying to test the library out on websocket.org. I am just trying to send a message and then print the response. I'm confused as to how to use/access the functions returned by ws_conn. I thought that I could do something like let push,print = ws_conn in or let push,print = Websocket.open_connection ~tls:false ws_addr in but that does not seem to be correct. Here is what I have so far.
#require "websocket";;
(* Set up the websocket uri address *)
let ws_addr = Uri.of_string "ws://echo.websocket.org"
(* Set up the websocket connection *)
let ws_conn = Websocket.open_connection ~tls:false ws_addr
(* Set up a frame *)
let ws_frame = Websocket.Frame.of_string "Rock it with HTML5 WebSocket"
(* Function to handle replies *)
let with_reply s =
match s with
| Some x ->
let line = Websocket.Frame.content x in
print_string line
| None ->
print_string "Error Recieved no reply ..."
Thanks nlucaroni, after further reading I have created a concrete example as an answer to my question.
#require "websocket";;
#require "lwt";;
#require "lwt.syntax";;
(* Set up the uri address *)
let ws_addr = Uri.of_string "ws://echo.websocket.org"
(* Set up the websocket connection *)
let ws_conn = Websocket.open_connection ~tls:false ws_addr
(* Function to print a frame reply *)
let f (x : Websocket.Frame.t) =
let s = Websocket.Frame.content x in
print_string s;
Lwt.return ()
(* push a string *)
let push_msg =
ws_conn
>>= fun (_, ws_pushfun) ->
let ws_frame = Websocket.Frame.of_string msg in
ws_pushfun (Some ws_frame);
Lwt.return ()
(* print stream element *)
let print_element () =
ws_conn
>>= fun (ws_stream, _) ->
Lwt_stream.next ws_stream
>>= f
(* push string and print response *)
let push_print msg =
ws_conn
>>= fun(ws_stream, ws_pushfun) ->
let ws_frame = Websocket.Frame.of_string msg in
ws_pushfun (Some ws_frame);
Lwt_stream.next ws_stream >>= f
The open_connection function returns,
(Frame.t Lwt_stream.t * (Frame.t option -> unit)) Lwt.t
the 'a Lwt.t is a thread that returns the pair of a print stream and a push function for your use. You use the 'a Lwt.t in a monadic way, and a simple tutorial can be found http://ocsigen.org/lwt/manual/ .

Return string and code optimisation in F#

How to modify below code to Return "string" so that returned output displayed on my MVC page and also would like to accept enteredChar from user.
Is there better way to do create this pyramid?
Current code:
let enteredChar = 'F' // As Interactive window doesn't support to Read Input
let mylist = ['A'..enteredChar]
let mylistlength = mylist |> List.length
let myfunc i x tlist1 =
(for j = 0 to mylistlength-i-2 do printf "%c" ' ')
let a1 = [for p in tlist1 do if p < x then yield p]
for p in a1 do printf "%c" p
printf "%c" x
let a2 = List.rev a1
for p in a2 do printf "%c" p
printfn "%s" " "
mylist |> List.iteri(fun i x -> myfunc i x mylist)
Output:
A
ABA
ABCBA
ABCDCBA
ABCDEDCBA
ABCDEFEDCBA
A few small optimizations could be:
Use StringBuilder instead of printf which is quite slow with long strings.
Use Array instead of List since Array works better with String.
Here is a version producing a pyramid string, which is kept closely to your code:
open System
open System.Text
let generateString c =
let sb = StringBuilder()
let generate i x arr =
String.replicate (Array.length arr-i-1) " " |> sb.Append |> ignore
let a1 = Array.filter (fun p -> p < x) arr
String(a1) |> sb.Append |> ignore
sb.Append x |> ignore
String(Array.rev a1) |> sb.Append |> ignore
sb.AppendLine " " |> ignore
let arr = [|'A'..c|]
arr |> Array.iteri(fun i x -> generate i x arr)
sb.ToString()
generateString 'F' |> printfn "%s"
As an alternative to Daniel's solution, you can achieve what you want with minimal changes to the code logic. Instead of using printf that writes the output to the console, you can use Printf.bprintf which writes the output to a specified StringBuilder. Then you can simply get the resulting string from the StringBuilder.
The modified function will look like this. I added parameter str and replaced printf with Printf.bprintf str (and printfn with bprintf together with additional \n char):
let myfunc i x tlist1 str =
(for j = 0 to mylistlength-i-2 do Printf.bprintf str "%c" ' ')
let a1 = [for p in tlist1 do if p < x then yield p]
for p in a1 do Printf.bprintf str "%c" p
Printf.bprintf str "%c" x
let a2 = List.rev a1
for p in a2 do Printf.bprintf str "%c" p
Printf.bprintf str "%s\n" " "
To call the function, you first create StringBuilder and then pass it to myfunc in every call. At the end, you can get the result using ToString method:
let str = StringBuilder()
mylist |> List.iteri(fun i x -> myfunc i x mylist str)
str.ToString()
I think Daniel's solution looks nicer, but this is the most direct way to tunr your printing code into a string-building code (and it can be done, pretty much, using Search & Replace).
If I understand your question (this likely belongs on Code Review) here's one way to rewrite your function:
let showPyramid (output: TextWriter) lastChar =
let chars = [|'A' .. lastChar|]
let getRowChars n =
let rec loop acc i =
[|
if i < n then let c = chars.[i] in yield c; yield! loop (c::acc) (i+1)
else yield! List.tail acc
|]
loop [] 0
let n = chars.Length
for r = 1 to n do
output.WriteLine("{0}{1}{0}", String(' ', n - r), String(getRowChars r))
Example
showPyramid Console.Out 'F'
or, to output to a string
use output = new StringWriter()
showPyramid output 'F'
let pyramid = output.ToString()
EDIT
After seeing Tomas' answer I realized I skipped over "return a string" in your question. I updated the code and added examples to show how you could do that.
let pyramid (ch:char) =
let ar = [| 'A'..ch |]
let len = ar.Length
Array.mapi
(fun i ch ->
let ar = ar.[0..i]
String.replicate (len - i - 1) " " + new string(ar) + new string((Array.rev ar).[1..]))
ar
|> String.concat "\n"
pyramid 'F' |> printfn "%s"
Here's another approach that seems to be a good demonstration of functional composition. I bet it's the shortest solution among the answers here. :)
let charsToString = Seq.map string >> String.concat String.Empty
let pyramid lastChar =
let src = '-'::['A'..lastChar] |> List.toArray
let len = Array.length src - 1
fun row col -> row-abs(col-len+1)+1 |> max 0 |> Array.get src // (1)
>> Seq.init (len*2-1) >> charsToString // (2)
|> Seq.init len // (3)
pyramid 'X' |> Seq.iter (printfn "%s")
First, we generate an unusual array of initial data. Its element [0] contains a space or whatever separator you want to have; I preferred dash (-) for debugging purposes.
The (1) line makes a function that calculates what character to be placed. The result of row-abs(col-len+1)+1 can be either positive (and there is a char to be placed) or zeronegative, and there should be a space. Note that there is no if statement: it is hidden within the max function;
The (2) line composes a function int -> string for generating an individual row;
The (3) line passes the function above as argument for sequence initializer.
The three lines can be written in a more verbose way:
let genCell row col = row-abs(col-len+1)+1 |> max 0 |> Array.get src
let genRow = genCell >> Seq.init (len*2-1) >> charsToString
Seq.init len genRow
Note genRow needs no formal argument due to functional composition: the argument is being bound into genCell, returning a function of a single argument, exactly what Seq.init needs.

Resources