What causes the REPL to print a function signature instead of function result?
I am attempting to execute the following line:
let email = Email "abc.com";;
email |> sendMessage |> ignore;;
The code is as follows
type PhoneNumber =
{ CountryCode:int
Number:string }
type ContactMethod =
| Email of string
| PhoneNumber of PhoneNumber
let sendMessage contact = function
| Email _ -> printf "Sending message via email"
| PhoneNumber phone -> printf "Sending message via phone"
// c. Create two values, one for the email address case and
// one for the phone number case, and pass them to sendMessage.
let email = Email "abc.com";;
email |> sendMessage |> ignore;;
I get the following result:
type PhoneNumber =
{CountryCode: int;
Number: string;}
type ContactMethod =
| Email of string
| PhoneNumber of PhoneNumber
val sendMessage : contact:'a -> _arg1:ContactMethod -> unit
val email : ContactMethod = Email "abc.com"
>
val it : unit = ()
I expected something like this:
"Sending message via email"
Your sendMessage function takes two arguments: one named contact of unrestricted type 'a and an anonymous (_arg1 in the signature) ContactMethod.
When you supply email to sendMessage you get a function which takes a ContactMethod and returns unit. You then ignore this function.
Either remove the contact parameter (more idiomatic):
let sendMessage = function
| Email _ -> printf "Sending message via email"
| PhoneNumber phone -> printf "Sending message via phone"
or match on it (might be easier to understand):
let sendMessage contact =
match contact with
| Email _ -> printf "Sending message via email"
| PhoneNumber phone -> printf "Sending message via phone"
Now, sendMessage is of type ContactMethod -> unit and you don't need to ignore anymore.
Related
Issue:
I am struggling to understand why my Reporter actor is not receiving messages based on the following statement that's in my Generator actor:
reporter <! Message input
My reporter actor is the following:
let reporterActor (mailbox:Actor<_>) =
let rec loop() = actor { let! msg = mailbox.Receive()
match msg |> box :?> Command with
| Start -> ()
| Message v -> printf "%s" v
| Exit -> mailbox.Context.System.Terminate() |> ignore }
loop() |> ignore
Basically, a console is launched that accepts input from the user. My Generator actor forwards that input to my Reporter actor. However, the code above never gets executed.
The code is the following:
module Main
open System
open Akka.FSharp
open Akka.Actor
open Actors
type Command =
| Message of string
| Start | Exit
let reporterActor (mailbox:Actor<_>) =
let rec loop() = actor { let! msg = mailbox.Receive()
match msg |> box :?> Command with
| Start -> ()
| Message v -> printf "%s" v
| Exit -> mailbox.Context.System.Terminate() |> ignore }
loop() |> ignore
let generatorActor (reporter:IActorRef) (mailbox:Actor<_>) message =
let handle input = match input with
| "exit" -> mailbox.Context.System.Terminate |> ignore
| _ -> reporter <! Message input
handle (Console.ReadLine().ToLower())
[<EntryPoint>]
let main argv =
let system = System.create "system" (Configuration.load())
let reporterActor = spawn system "reporterActor" (actorOf(reporterActor))
let generatorActor = spawn system "generatorActor" (actorOf2(generatorActor reporterActor))
generatorActor <! Start
system.AwaitTermination ()
0
Update:
I learned that I could trigger my Reporter actor by replacing the mailbox parameter with an arbitrary message parameter:
let reporterActor message =
match message |> box :?> Command with
| Start -> ()
| Message v -> printf "Reporting: %s" v
| Exit -> failwith "Kill this!"
I still don't understand when I should use a mailbox parameter versus when I should rely on a message parameter.
The difference is in how actorOf and actorOf2 work.
actorOf in conjunction with spawn creates an actor as a child of the root of the system which will handle messages with the function 'Message -> unit that was passed to it.
actorOf2 in in conjunction with spawn creates an actor as a child of the actor that you passed in and the child will handle the messages with the function 'Message -> unit that was passed.
Your original function signature for reporter actor was:
Actor<'Message> -> unit
and you used spawn system "reporterActor" (actorOf(reporterActor))
In this case you were saying that the message type that the new actor that was created would receive would be of type Actor<'Message> . This compiled because actorof just expects a function that takes a 'Message, and a 'Message is generic therefore Actor<'Message> satisfied the 'Message parameter.
When you updated the signature of reporterActor you change the signature to 'Message -> unit which is what actorOf is actually intended to accept.
In short generics allowed your code to compile since 'Message isn't really restricted, nor should it really be.
From: http://getakka.net/docs/FSharp%20API
actorOf (fn : 'Message -> unit) (mailbox : Actor<'Message>) :
Cont<'Message, 'Returned> - uses a function, which takes a message as
the only parameter. Mailbox parameter is injected by spawning
functions.
actorOf2 (fn : Actor<'Message> -> 'Message -> unit) (mailbox :
Actor<'Message>) : Cont<'Message, 'Returned> - uses a function, which
takes both the message and an Actor instance as the parameters.
Mailbox parameter is injected by spawning functions. Example:
> let handleMessage (mailbox: Actor<'a>) msg =
> match msg with
> | Some x -> printf "%A" x
> | None -> ()
>
> let aref = spawn system "my-actor" (actorOf2 handleMessage) let
> blackHole = spawn system "black-hole" (actorOf (fun msg -> ()))
spawn (actorFactory : IActorRefFactory) (name : string) (f :
Actor<'Message> -> Cont<'Message, 'Returned>) : IActorRef - spawns an
actor using a specified actor computation expression. The actor can
only be used locally.
All of these functions may be used with either the actor system or the
actor itself. In the first case the spawned actor will be placed under
/user root guardian of the current actor system hierarchy. In the
second option the spawned actor will become a child of the actor used
as the actorFactory parameter of the spawning function.
I have tried following code to view/capture dead letters but it is not working in a way it should. What I am missing.exactly? My aim is just to view all the dead letters that are being delivered to deadletters actor.
let system = ActorSystem.Create("FSharp")
let echoServer =
spawn system "EchoServer"
<| fun mailbox ->
let rec loop() =
actor {
let! message = mailbox.Receive()
match box message with
| :? string ->
printfn "Echo '%s'" message
return! loop()
| _ -> failwith "unknown message"
}
loop()
let boolval = system.EventStream.Subscribe(echoServer,typedefof<DeadLetterActorRef>)
echoServer.Tell("First Message")
echoServer.Tell("Second Message")
system.DeadLetters.Tell("Dead Message")
When you subscribe to the event bus, you're subscribing to the type of message published to the bus. In the code you posted you registered the subscriber to the DeadLetterActorRef message, whereas dead letters are published in the form of DeadLetter messages. So in your case, you just need to change your subscription to
let boolval = system.EventStream.Subscribe(echoServer, typeof<DeadLetter>)
I've been working my way through this article on ROP, and have reached the section "Converting simple functions to the railway-oriented programming model" where he explains how to fit other kinds of functions into the model.
He gave the example of wanting to clean an email address (function name different as I'm English!)...
let cleanEmail person =
printfn "Cleaning email for \"%s\"" person.Name
let newPerson = { person with Email = person.Email.Trim().ToLower() }
printfn " email is now \"%s\"" newPerson.Email
newPerson
I added some printfn to see what was happening. This function works fine, in that if I pass it an input with an email that has uppercase letters and/or leading/trailing blanks, the output is a value with a clean, lowercase email address...
let shouter = { Name = "Jim"; Email = " JIM#SHOUT.com "}
cleanEmail shouter
Gives the output...
Cleaning email for "Jim"
email is now "jim#shout.com"
val it : Request = {Name = "Jim";
Email = "jim#shout.com";}
However, if I wrap this function in a switch, and insert it into the chain of validation functions, the original email address is used. For example, with validation functions like this...
let validateNameNotBlank person =
printfn "Validating name not blank for \"%s\"" person.Name
if person.Name = "" then Failure "Name must not be blank"
else Success person
...an operator like this...
let (>=>) switch1 switch2 input =
match switch1 input with
| Success s -> switch2 input
| Failure f -> Failure f
...and bound together like this...
let validate =
validateNameNotBlank
>=> validateNameLength
>=> switch cleanEmail
>=> validateEmail
...then when I pass shouter in, I get the following out...
Validating name not blank for "Jim"
Validating name length for "Jim"
Cleaning email for "Jim"
email is now "jim#shout.com"
Validating email for "Jim" ( JIM#SHOUT.com )
val it : Result<Request,string> = Success {Name = "Jim";
Email = " JIM#SHOUT.com ";}
You can see from the printfn I put in that the cleanEmail function is cleaning the email, but the output shows that the original email is passed to the next function in the chain.
What have I missed here?
If you look at the article, the operator has the definition
let (>=>) switch1 switch2 x =
match switch1 x with
| Success s -> switch2 s
| Failure f -> Failure f
which when correctly translated to your variables is:
let (>=>) switch1 switch2 input =
match switch1 input with
| Success s -> switch2 s
| Failure f -> Failure f
You never actually use the s from the Success so the same input just keeps getting passed through.
A close examination of the type of >=> would have revealed this problem as yours would have given the same type to switch1 and switch2 when they should have different types.
How do I retrieve a value from a generic?
Specifically, I am attempting the following:
// Test
let result = Validate goodInput;;
// How to access record??
let request = getRequest result
Here's the code:
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
let bind nextFunction lastFunctionResult =
match lastFunctionResult with
| Success input -> nextFunction input
| Failure f -> Failure f
type Request = {name:string; email:string}
let validate1 input =
if input.name = "" then Failure "Name must not be blank"
else Success input
let validate2 input =
if input.name.Length > 50 then Failure "Name must not be longer than 50 chars"
else Success input
let validate3 input =
if input.email = "" then Failure "Email must not be blank"
else Success input;;
let Validate =
validate1
>> bind validate2
>> bind validate3;;
// Setup
let goodInput = {name="Alice"; email="abc#abc.com"}
let badInput = {name=""; email="abc#abc.com"};;
// I have no clue how to do this...
let getRequest = function
| "Alice", "abc#abc.com" -> {name="Scott"; email="xyz#xyz.com"}
| _ -> {name="none"; email="none"}
// Test
let result = Validate goodInput;;
// How to access record??
let request = getRequest result
printfn "%A" result
You mean how do you extract the record out of your result type? Through pattern matching, that's what you're already doing in bind.
let getRequest result =
match result with
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
let result = Validate goodInput
let record = getRequest result
This will return the record or throw an exception. Up to you how you handle the success and failure cases once you have your Result - that could be throwing an exception, or turning it into option, or logging the message and returning a default etc.
This seems to be a frequently asked question: How do I get the value out of a monadic value? The correct answer, I believe, is Mu.
The monadic value is the value.
It's like asking, how do I get the value out of a list of integers, like [1;3;3;7]?
You don't; the list is the value.
Perhaps, then, you'd argue that lists aren't Discriminated Unions; they have no mutually exclusive cases, like the above Result<'TSuccess,'TFailure>. Consider, instead, a tree:
type Tree<'a> = Node of Tree<'a> list | Leaf of 'a
This is another Discriminated Union. Examples include:
let t1 = Leaf 42
let t2 = Node [Node []; Node[Leaf 1; Leaf 3]; Node[Leaf 3; Leaf 7]]
How do you get the value out of a tree? You don't; the tree is the value.
Like 'a option in F#, the above Result<'TSuccess,'TFailure> type (really, it's the Either monad) is deceptive, because it seems like there should only be one value: the success. The failure we don't like to think about (just like we don't like to think about None).
The type, however, doesn't work like that. The failure case is just as important as the success case. The Either monad is often used to model error handling, and the entire point of it is to have a type-safe way to deal with errors, instead of exceptions, which are nothing more than specialised, non-deterministic GOTO blocks.
This is the reason the Result<'TSuccess,'TFailure> type comes with bind, map, and lots of other goodies.
A monadic type is what Scott Wlaschin calls an 'elevated world'. While you work with the type, you're not supposed to pull data out of that world. Rather, you're supposed to elevate data and functions up to that world.
Going back to the above code, imagine that given a valid Request value, you'd like to send an email to that address. Therefore, you write the following (impure) function:
let send { name = name; email = email } =
// Send email using name and email
This function has the type Request -> unit. Notice that it's not elevated into the Either world. Still, you want to send the email if the request was valid, so you elevate the send method up to the Either world:
let map f = bind (fun x -> Success (f x))
let run = validate1 >> bind validate2 >> bind validate3 >> map send
The run function has the type Request -> Result<unit,string>, so used with goodInput and badInput, the results are the following:
> run goodInput;;
val it : Result<unit,string> = Success unit
> run badInput;;
val it : Result<unit,string> = Failure "Name must not be blank"
And then you probably ask: and how do I get the value out of that?
The answer to that question depends entirely on what you want to do with the value, but, imagine that you want to report the result of run back to the user. Displaying something to the user often involves some text, and you can easily convert a result to a string:
let reportOnRun = function
| Success () -> "Email was sent."
| Failure msg -> msg
This function has the type Result<unit,string> -> string, so you can use it to report on any result:
> run goodInput |> reportOnRun;;
val it : string = "Email was sent."
> run badInput |> reportOnRun;;
val it : string = "Name must not be blank"
In all cases, you get back a string that you can display to the user.
I need help understanding the concepts behind the following:
I have this:
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
But this doesn't work:
let getRequest = function
| Success input -> input
| Failure msg -> msg
But this does:
let getRequest result =
match result with
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
Why does the initial "getRequest" fail?
Again, I just don't understand the basic rules for pattern matching.
Can someone please shed some light on this?
The entire code is here:
module Core
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
let bind nextFunction lastFunctionResult =
match lastFunctionResult with
| Success input -> nextFunction input
| Failure f -> Failure f
type Request = {Name:string; Email:string}
let validate1 input =
if input.Name = "" then Failure "Name must not be blank"
else Success input
let validate2 input =
if input.Name.Length > 50 then Failure "Name must not be longer than 50 chars"
else Success input
let validate3 input =
if input.Email = "" then Failure "Email must not be blank"
else Success input;;
let Validate =
validate1
>> bind validate2
>> bind validate3;;
// Setup
let goodInput = {Name="Alice"; Email="abc#abc.com"}
let badInput = {Name=""; Email="abc#abc.com"};;
let getRequest = function
| Success input -> input
| Failure msg -> msg
// Test
let result = Validate goodInput;;
let request = getRequest result;;
Given this definition
let getRequest = function
| Success input -> input
| Failure msg -> msg
we can reason about its type as follows:
Since it's a function, it has type ?1 -> ?2 for some not-yet-known placeholder types.
The input uses the Success and Failure union cases, so the input must itself actually be some type Result<?3,?4>, and the function's type is Result<?3,?4> -> ?2.
The types of each branch must be the same as the function's return type.
Looking at the first branch, we see this means that ?3 = ?2.
Looking at the second branch, this means that ?4 = ?2.
Therefore the overall type of the function must be Result<?2,?2> -> ?2, or using real F# notation, Result<'a,'a> -> 'a where 'a can be any type - this is a generic function definition.
But Validate has type Request -> Result<Request, string>, so its output isn't consistent with this definition of getResult because the success and failure types are different and you can't just directly pass the results from one to the other.
On the other hand, with
let getRequest = function
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
we would analyze it like this:
As before, any function has type ?1 -> ?2.
As before, the input must clearly be a Result<?3,?4>.
But analyzing the branches, we get a different result:
The first branch again leads to the constraint ?3 = ?2.
But the second branch is different - failwithf with that format pattern takes a string and throws an exception (and can have any return type, since it never returns normally), so we see msg must be a string, so ?4 = string.
So the overall type is Result<'a,string> -> 'a, which now allows you to pass a Result<Request,string> to it, as desired.
I think your question actually gives a good platform to explain pattern matching.
Let's start by thinking about the types involved, your getRequest function must be a function with some type signature getRequest : 'a -> 'b', i.e. it takes something of one type and returns something of another but let's look at what you've written.
let getRequest =
function
| Success input -> input // this branch would return 'TSuccess
| Failure msg -> msg // this brach would return 'TFailure
You can't have a function whose type signature is 'a -> 'b or 'c. (The only way to make this function compile is if 'b and 'c can be constrained to be the same type, then we do simply have a consistent 'a -> 'b).
But wait, enter the discriminated union.
Your discriminated union has type Result<'TSuccess,'TFailure>. Or, to describe things as I did above type 'd<'b,'c>. Now, we absolutely can have a function whose type signature is 'a -> 'd<'b,'c>.
'd<'b, 'c> is just a generic type which involves 'b and it involves 'c. The type signature includes all of these things, so hopefully you can see that we can contain both a 'TSuccess and 'TFailure in this type with no problem.
So, if we want to return something which can contain different combinations of types, we've found the perfect use case for the discriminated union. It can contain the 'TSuccess or the 'TFailure in one type. You can then choose between those results using pattern matching.
let getRequest =
function
| Success input -> printfn "%A" input // do something with success case
| Failure msg -> printfn "%A" msg // do something with failure case
So long as we have consistent return types in each case, we can insert any behaviour we want.
On to the next point of why throwing an exception is okay. Let's look at the type signature of the failwithf function: failwithf : StringFormat<'T,'Result> -> 'T. The failwithf function takes a string format and returns some type 'T.
So let's look at your second function again
let getRequest result =
match result with
| Success input -> input // type 'TSuccess
| Failure msg -> failwithf "Invalid input: %s" msg // type 'T inferred to be 'TSuccess
The function signature is consistent, 'a -> 'TSuccess.