I'm new to F# so forgive me in advance if this is a stupid question or if the syntax may be a bit off. Hopefully it's possible to understand the gist of the question anyways.
What I'd like to achieve is the possibility to compose e.g. Result's (or an Either or something similar) having different error types (discriminated unions) without creating an explicit discriminated union that includes the union of the two other discriminated unions.
Let me present an example.
Let's say I have a type Person defined like this:
type Person =
{ Name: string
Email: string }
Imagine that you have a function that validates the name:
type NameValidationError =
| NameTooLong
| NameTooShort
let validateName person : Result<Person, NameValidationError>
and another that validates an email address:
type EmailValidationError =
| EmailTooLong
| EmailTooShort
let validateEmail person : Result<Person, EmailValidationError>
Now I want to compose validateName and validateEmail, but the problem is that the error type in the Result has different types. What I'd like to achieve is a function (or operator) that allows me to do something like this:
let validatedPerson = person |> validateName |>>> validateEmail
(|>>> is the "magic operator")
By using |>>> the error type of validatedPerson would be a union of NameValidationError and EmailValidationError:
Result<Person, NameValidationError | EmailValidationError>
Just to make it clear, it should be possible to an use arbitrary number of functions in the composition chain, i.e.:
let validatedPerson : Result<Person, NameValidationError | EmailValidationError | XValidationError | YValidationError> =
person |> validateName |>>> validateEmail |>>> validateX |>>> validateY
In languages like ReasonML you can use something called polymorphic variants but this is not available in F# as afaict.
Would it be possible to somehow mimic polymorphic variants using generics with union types (or any other technique)?! Or is this impossible?
There's some interesting proposals for erased type unions, allowing for Typescript-style anonymous union constraints.
type Goose = Goose of int
type Cardinal = Cardinal of int
type Mallard = Mallard of int
// a type abbreviation for an erased anonymous union
type Bird = (Goose | Cardinal | Mallard)
The magic operator which would give you a NameValidationError | EmailValidationError would have its type exist only at compile-time. It would be erased to object at runtime.
But it's still on the anvil, so maybe we can still have some readable code by doing the erasing ourselves?
The composition operator could 'erase' (box, really) the result error type:
let (|>>) input validate =
match input with
| Ok(v) -> validate v |> Result.mapError(box)
| Error(e) -> Error(box e)
and we can have a partial active pattern to make type-matching DU cases palatable.
let (|ValidationError|_|) kind = function
| Error(err) when Object.Equals(kind, err) -> Some ()
| _ -> None
Example (with super biased validations):
let person = { Name = "Bob"; Email = "bob#email.com "}
let validateName person = Result.Ok(person)
let validateEmail person = Result.Ok(person)
let validateVibe person = Result.Error(NameTooShort)
let result = person |> validateName |>> validateVibe |>> validateEmail
match result with
| ValidationError NameTooShort -> printfn "Why is your name too short"
| ValidationError EmailTooLong -> printfn "That was a long address"
| _ -> ()
This will shunt on validateVibe
This is probably more verbose than you would like but it does allow you to put things into a DU without explicitly defining it.
F# has Choice types which are defined like this:
type Choice<'T1,'T2> =
| Choice1Of2 of 'T1
| Choice2Of2 of 'T2
type Choice<'T1,'T2,'T3> =
| Choice1Of3 of 'T1
| Choice2Of3 of 'T2
| Choice3Of3 of 'T3
// Going up to ChoiceXOf7
With your existing functions you would use them like this:
// This function returns Result<Person,Choice<NameValidationError,EmailValidationError>>
let validatePerson person =
validateName person
|> Result.mapError Choice1Of2
|> Result.bind (validateEmail >> Result.mapError Choice2Of2)
This is how you would consume the result:
let displayValidationError person =
match person with
| Ok p -> None
| Error (Choice1Of2 NameTooLong) -> Some "Name too long"
| Error (Choice2Of2 EmailTooLong) -> Some "Email too long"
// etc.
If you want to add a third validation into validatePerson you'll need to switch to Choice<_,_,_> DU cases, e.g. Choice1Of3 and so on.
Related
I just started programming functionally. My current tiny project to start would be a basic pokemon battle.
Code first, explanation follows.
let choosePokemon () =
let mutable pokemon = DemoData.schiggy
let msg = Console.ReadLine()
match msg with
| "Schiggy" -> pokemon <- DemoData.schiggy
| "Pikachu" -> pokemon <- DemoData.pikachu
| "Kleinstein" -> pokemon <- DemoData.kleinstein
| "Karpador" -> pokemon <- DemoData.karpador
pokemon
I am currently asking people to enter the name of a Pokemon and if it matches a predefined set (Schiggy, Pikachu, Kleinstein or Karpador) it gives them the respective Pokemon. Alternatively it gives them the default Pokemon.
I am currently creating it before matching it with "let mutable pokemon = DemoData.schiggy". I don't want that. I just want to assign it based on its name.
If I could go without that line I'd avoid making it mutable, which is something I don't want anyways.
Additional question further down the line: When Pokemon attack each other their hp will decrease.
How can I avoid using a mutable int when facing a changing int value?
Thanks in advance :)
Just return the result from the match - there's no need to declare a variable:
let choosePokemon () =
let msg = Console.ReadLine()
match msg with
| "Schiggy" -> DemoData.schiggy
| "Pikachu" -> DemoData.pikachu
| "Kleinstein" -> DemoData.kleinstein
| "Karpador" -> DemoData.karpador
The function is still impure, though, since it performs I/O (Console.ReadLine)...
It's also partial, since it'll crash on any other input than the four strings being matched. Even misspellings and case mistakes are going to throw an exception.
A more robust pure function would be something like this:
let choosePokemon (input : string) =
match input.Trim().ToUpperInvariant () with
| "PIKACHU" -> DemoData.pikachu
| "KLEINSTEIN" -> DemoData.kleinstein
| "KARPADOR" -> DemoData.karpador
| _ -> DemoData.schiggy
Contrary to the OP that performs I/O, this version is a pure function, since there's no non-deterministic behaviour. It's also total, since it returns schiggy as a default value.
To get the behaviour where you ask the user to input a value, compose the impure Console.ReadLine action with the pure choosePokemon function:
Console.ReadLine >> choosePokemon
Terminology
For the following post, I will use the term "reference enum" to refer to an F# type that is a discriminated union with no fields in each case. For example:
type AReferenceEnum = Yes | No | Maybe
Requirements
I need a function that given a Type, returns a bool that tells whether the type is a reference enum or not.
Given these types:
type AReferenceEnum = Yes | No | Maybe
type ARecord = { name : string }
type AUnion = This of int | That of (int * string)
type AEnum = Left = 1 | Right = 2
The function would return these values
isReferenceEnum typeof<AReferenceEnum> -> true
isReferenceEnum typeof<ARecord> -> false
isReferenceEnum typeof<AUnion> -> false
isReferenceEnum typeof<AEnum> -> false
What I've tried
It seems like the implementation could be done using FSharpType and FSharpValue in the FSharp.Reflection namespace.
I know you can check FSharpType.IsUnion t to check if a type is a union, which includes reference enums.
I know you can check FSharpType.GetUnionCases t to get a UnionCaseInfo[] describing the different cases of the union type.
I know you can check FSharpValue.GetUnionFields (value, type) to get the fields of the case that value is an instance of, but not other cases.
If I could iterate the fields of each case of the union, then I could check that all cases have 0 fields, and then the type would be a reference enum.
Any suggestions?
This passes your test cases:
let isReferenceEnum ty =
if FSharpType.IsUnion ty then
FSharpType.GetUnionCases ty
|> Array.forall (fun i -> i.GetFields().Length = 0)
else
false
I'm new to Elmish.Xamarin and Xamarin itself. I'm trying to build an application, using this calculator example. Main difference is that in this example UI is updated upon user input, and update function is pure and just evaluates next state of model:
let update msg model =
match msg with
| Clear -> Initial
| Digit digit ->
match model with
| Initial | Error | Result _ -> Operand (double digit)
| Operand op -> Operand (double (string op + string digit))
| OperandOperator (operand, operator) -> OperandOperatorOperand (operand, operator, double digit)
| OperandOperatorOperand (op1, operator, op2) -> OperandOperatorOperand (op1, operator, double (string op2 + string digit))
| Operator operator ->
match model with
| Initial | Error -> model
| Result operand // previously calculated result is now the first operand
| Operand operand | OperandOperator (operand, _) -> OperandOperator(operand, operator)
| OperandOperatorOperand _ -> calculate model msg
| Equals -> calculate model msg
I need a different scenario: user's input doesn't affect UI directly, instead I store user's messages and evaluate next state on schedule, so in my app's core I pass updateUI: gameState -> unit func:
let gameAgentFn (mailboxNetwork: MailboxNetwork) updateUi gameState cmd =
let timerAgent = timerAgent mailboxNetwork
match gameState.gameFrame with
| Frame field ->
let gameState = Game.updateGameState gameState cmd
timerAgent.Post Next
updateUi gameState
gameState
Problem is I can't understand, what function to pass and how to build interaction with this design, since as far as I can see, it expects me to pass pure function to evaluate next state and the rest is being done underneath.
I have a recursive function that contains a series of matches that either make the recursive call back to the function, or make a call to failwith.
This is basically a hybrid implementation of the recursive descent parser descibed in Don Syme's Expert F# book (page 180) and the parsing example shown here: http://fsharpforfunandprofit.com/posts/pattern-matching-command-line/
Here is a snippet of my own code.
let rec parseTokenListRec tokenList optionsSoFar =
match tokenList with
| [] -> optionsSoFar
| SOURCE::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Source = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the source argument."
| REGISTRY::t ->
...
A full code listing can be found at http://fssnip.net/nU
The way the code is currently written, when the function has finished working its way through the tokenList, it will return the optionsSoFar record that has been compiled via the object expression {optionsSoFar with Source = (returnConcatHeadValues t)}, or it will throw an exception if an invalid argument is found.
I want to refactor this so that the function does not rely on an exception, but will always return a value of some sort that can be handled by the calling function. The idea I have is to return a discriminated union rather than a record.
This discriminated union would be something like
type Result =
|Success of Options
|Failure of string
The problem I had when I tried to refactor the code was that I couldn't figure out how to get the success value of the DU to initialize via an object expression. Is this possible?
The examples I've looked at on MSDN (http://msdn.microsoft.com/en-us/library/vstudio/dd233237(v=vs.100).aspx), fsharpforfunandprofit (http://fsharpforfunandprofit.com/posts/discriminated-unions/) and elsewhere haven't quite cleared this up for me.
I'm worried that I'm not making any sense here. I'm happy to clarify if needed.
If I understand it correctly, in you current solution, the type of optionsSoFar is Options. The code becomes trickier if you change the type of optionsSoFar to your newly defined Result.
However, I think you do not need to do that - you can keep optionsSoFar : Options and change the function to return Result. This works because you never need to call the function recursively after it fails:
let rec parseTokenListRec tokenList optionsSoFar =
match tokenList with
| [] -> Success optionsSoFar
| SOURCE::t ->
match t with
| VALUE x::tt ->
{optionsSoFar with Source = (returnConcatHeadValues t)}
|> parseTokenListRec (returnNonValueTail t)
| _ -> Failure "Expected a value after the source argument."
| REGISTRY::t -> ...
If you actually wanted to update Source in a Result value, then I'd probably write something like:
module Result =
let map f = function
| Success opt -> f opt
| Failure msg -> Failure msg
Then you could write a transformation as follows:
resultSoFar
|> Result.map (fun opts -> {opts with Source = returnConcatHeadValues t})
|> parseTokenListRec (returnNonValueTail t)
I'm trying to iterate through an array of objects and recursively print out each objects properties.
Here is my object model:
type firmIdentifier = {
firmId: int ;
firmName: string ;
}
type authorIdentifier = {
authorId: int ;
authorName: string ;
firm: firmIdentifier ;
}
type denormalizedSuggestedTradeRecommendations = {
id: int ;
ticker: string ;
direction: string ;
author: authorIdentifier ;
}
Here is how I am instantiating my objects:
let getMyIdeasIdeas = [|
{id=1; ticker="msfqt"; direction="buy";
author={authorId=0; authorName="john Smith"; firm={firmId=12; firmName="Firm1"}};};
{id=2; ticker="goog"; direction="sell";
author={authorId=1; authorName="Bill Jones"; firm={firmId=13; firmName="ABC Financial"}};};
{id=3; ticker="DFHF"; direction="buy";
author={authorId=2; authorName="Ron James"; firm={firmId=2; firmName="DEFFirm"}};}|]
And here is my algorithm to iterate, recurse and print:
let rec recurseObj (sb : StringBuilder) o=
let props : PropertyInfo [] = o.GetType().GetProperties()
sb.Append( o.GetType().ToString()) |> ignore
for x in props do
let getMethod = x.GetGetMethod()
let value = getMethod.Invoke(o, Array.empty)
ignore <|
match value with
| :? float | :? int | :? string | :? bool as f -> sb.Append(x.Name + ": " + f.ToString() + "," ) |> ignore
| _ -> recurseObj sb value
for x in getMyIdeas do
recurseObj sb x
sb.Append("\r\n") |> ignore
If you couldnt tell, I'm trying to create a csv file and am printing out the types for debugging purposes. The problem is, the first element comes through in the order you'd expect, but all subsequent elements come through with a slightly different (and confusing) ordering of the "child" properties like so:
RpcMethods+denormalizedSuggestedTradeRecommendationsid:
1,ticker: msfqt,direction:
buy,RpcMethods+authorIdentifierauthorId:
0,authorName: john
Smith,RpcMethods+firmIdentifierfirmId:
12,firmName: Firm1,
RpcMethods+denormalizedSuggestedTradeRecommendationsid:
2,ticker: goog,direction:
sell,RpcMethods+authorIdentifierauthorName:
Bill
Jones,RpcMethods+firmIdentifierfirmName:
ABC Financial,firmId: 13,authorId: 1,
RpcMethods+denormalizedSuggestedTradeRecommendationsid:
3,ticker: DFHF,direction:
buy,RpcMethods+authorIdentifierauthorName:
Ron
James,RpcMethods+firmIdentifierfirmName:
DEFFirm,firmId: 2,authorId: 2,
Any idea what is going on here?
Does adding this help?
for x in props |> Array.sortBy (fun p -> p.Name) do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In general, I think reflection returns entities (like attributes, methods, properties) in an unspecified order. So just pick a fixed sort order?
(Or did I misunderstand the issue?)
This is a reflection thing. You can't rely on the order of the properties using reflection. I need to sort using MetaTokens. I will post this solution when I get around to implementing it.