How can I make this match expression more concise? - f#

Learning F# by writing blackjack. I have these types:
type Suit =
| Heart = 0
| Spade = 1
| Diamond = 2
| Club = 3
type Card =
| Ace of Suit
| King of Suit
| Queen of Suit
| Jack of Suit
| ValueCard of int * Suit
I have this function (ignoring for now that aces can have 2 different values):
let NumericValue =
function | Ace(Suit.Heart) | Ace(Suit.Spade) | Ace(Suit.Diamond) | Ace(Suit.Club) -> 11
| King(Suit.Heart) | King(Suit.Spade)| King(Suit.Diamond) | King(Suit.Club) | Queen(Suit.Heart) | Queen(Suit.Spade)| Queen(Suit.Diamond) | Queen(Suit.Club) | Jack(Suit.Heart) | Jack(Suit.Spade)| Jack(Suit.Diamond) | Jack(Suit.Club) -> 10
| ValueCard(num, x) -> num
Is there a way I can include a range or something? Like [Ace(Suit.Heart) .. Ace(Suit.Club)]. Or even better Ace(*)

You want a wildcard pattern. The spec (ยง7.4) says:
The pattern _ is a wildcard pattern and matches any input.
let numericValue = function
| Ace _-> 11
| King _
| Queen _
| Jack _ -> 10
| ValueCard(num, _) -> num

Related

MQL help required, how to generate key

I am struggling with one code line. It is a Key generation Line for a Expert Adviser. Can someone help me figure out how I can generate key by using this line:
int key=3*(StringToInteger(StringSubstr(IntegerToString(AccountNumber()), 0, 3)))+333333;
And what is the problem?
int accountNumber = AccountNumber();
string accountNumberString = IntegerToString(accountNumber);
string accountNumberStringFirst3Digits=
StringSubstr(accountNumberString,0,3);
int accountNumberFirstThreeDigits = StringToInteger(accountNumberStringFirst3Digits);
int accountNumberFirstThreeDigitsMultiplied = 3 * accountNumberFirstThreeDigits;
int key = accountNumberFirstThreeDigitsMultiplied + 333333;
Can someone help me figure out how to generate key by this line?
Welcome, certainly, let's look on that :
int key = 3*(StringToInteger(StringSubstr(IntegerToString(AccountNumber()), 0, 3)))+333333;
Your code actually means this:
// +------------------------------------------------------------------------------- type declaration
// | +--------------------------------------------------------------------------- variable name definition
// | | +------------------------------------------------------------------------- assignment operator
// | | | +----------------------------------------------------------------------- compile-time integer constant
// | | | | +--------------------------------------------------------------------- multiply operator
// | | | | | +-------------------------------------------------- MT4 system function: StringToInteger( aString )
// | | | | | | +------------------------------------ MT4 system function: StringSubstr( aString, aPosToStartSubstrFrom, aSubstrLength )
// | | | | | | | +------------------- MT4 system function: IntegerToString( aIntNum ) | |
// | | | | | | | | +---- MT4 system function: AccountNumber() | |
// | | | | | | | | | | |
// | | | | | | | | | +------------------------------------------------------------------+ |
// | | | | | | | | | | +------------------------------------------------------------------------------+
// | | | | | | | | | | |
int key = 3 * ( StringToInteger( StringSubstr( IntegerToString( AccountNumber() ), 0, 3 ) ) )
+ 333333;
// | ||
// +------||----------------------------------------------------------------- add operator
// +|----------------------------------------------------------------- compile-time integer constant
// +----------------------------------------------------------------- literal MQL4-language syntax-terminator
The code above both defines and generates a fair integer value, so wherever your Expert Advisor code refers to a value of key, this calculated value will be used ( see also the documentation about the New-MQL4 scope-of-validity, inside which this variable remains visible ).

Is there a way to encapsulate a pattern in F#?

Is there a way to encapsulate a pattern in F#?
For example, instead of writing this...
let stringToMatch = "example1"
match stringToMatch with
| "example1" | "example2" | "example3" -> ...
| "example4" | "example5" | "example6" -> ...
| _ -> ...
Is there some way to accomplish something along these lines...
let match1to3 = | "example1" | "example2" | "example3"
let match4to6 = | "example4" | "example5" | "example6"
match stringToMatch with
| match1to3 -> ...
| match4to6 -> ...
| _ -> ...
You can do this with Active Patterns:
let (|Match1to3|_|) text =
match text with
| "example1" | "example2" | "example3" -> Some text
| _ -> None
let (|Match4to6|_|) text =
match text with
| "example4" | "example5" | "example6" -> Some text
| _ -> None
match stringToMatch with
| Match1to3 text -> ....
| Match4to6 text -> ....
| _ -> ...

New to F# and Don't Know How to Fix FS0025 error

I'm struggling trying to teach myself F# (my very first functional programming language) by building a very important app (or trying to) that will record user input and write to a JSON file (or eventually, a database) the outcomes of requests for help made by poor trafficking survivors to all the anti-trafficking charities/NGO's in the US. I keep getting this error, after trying everything I could think of to make sure that all possible cases for the pattern in question were considered. I don't know how to fix it, and I really can't use any error suppression on this app. Any help at all would be greatly appreciated, as I have no one else to reach out to for any help and support. Here is my code from the TerminalBuilder.fs file:
namespace Nonprofits
module TerminalBuilder =
open System
open System.IO
open Nonprofits.Types
let rec caller():Caller =
printfn "Are you reporting as an advocate on behalf of someone else or for yourself?"
printfn " 1 for Advocate"
printfn " 2 for Self"
let answer = Console.ReadLine()
match answer with
| "1" -> Advocate
| "2" -> ClientOrVictim
| _ -> printfn "Invalid Entry"
caller()
let specialneeds():Set<Disability> =
let rec spnds(s:Set<Disability>): Set<Disability> =
printfn "Do you/the person on whose behalf you're reporting have any disabling conditions?"
printfn " 1 for Learning Disability"
printfn " 2 for Physical Disability"
printfn " 3 for Mental Health Issues"
printfn " 4 for Substance Addiction Issues"
printfn " 5 for Pregnancy-Related Limitations"
printfn " 6 for Chronic Illness"
printfn " 7 for Don't KNow/Undiagnosed"
printfn " Enter 'Exit' for None"
let answer = Console.ReadLine()
match answer.Trim().ToLower() with
| "exit" -> s
| _ ->
let sn =
match answer.Trim().ToLower() with
| "1" -> Some LearningDisabled
| "2" -> Some PhysicallyDisabled
| "3" -> Some MentalIllness
| "4" -> Some SubstanceAddiction
| "5" -> Some Pregnancy
| "6" -> Some ChronicIllness
| "7" -> Some Undiagnosed
| "exit" -> printfn "No disabling conditions"
None
match sn with
| None -> spnds(s)
| Some (x) -> spnds(s.Add(x))
spnds(new Set<Disability> ([]))
And here is my types file, Nonprofits.fs:
namespace Nonprofits
open System.Collections
module Types =
type NgoType =
| HomelessShelter
| DVShelter
| TraffickingVictimSafehouse
| TraffickingSurvivorAftercare // gamut of legal, housing, clothing, food, medical, reintegration, etc.
| FoodPantries
| ClothingAssistance
| FreeMedicalDentalClinic
type Ngo = Ngo of NgoType * string
type Caller =
| ClientOrVictim
| Advocate
and CallerStatus =
| VictimServicesAdvocate of Caller
| DVvictim of Caller
| SexTraffickingSurvivor of Caller
| HomelessVictim of Caller
| NaturalDisasterVictim of Caller
| GeneralPovertyVictim of Caller
and Disability =
| Pregnancy
| PhysicallyDisabled
| LearningDisabled
| MentalIllness
| SubstanceAddiction
| ChronicIllness
| Undiagnosed
and SpecialNeeds = SpecialNeeds of Set<Disability>
type UnmetNeeds =
| TraffickingSafebed
| DVsafebed
| Housing
| Clothing
| Food
| Legal
| Medical
| Dental
| Vision
| DrugRehab
| TraumaCare
| PsychiatricCare
| SkillsTraining
| EducationHelp
| JobPlacement
| EconomicSupport
type CallerRequest =
| TraffickingVictimAftercare of Set<UnmetNeeds>
| PovertyVictimCare of Set<UnmetNeeds>
type Followup =
| SocialWorkerFollowup of Help
| CallerSelfDirected of Help
and Help =
| Helped //fully helped with everything caller needed
| ExhaustedOptions // exhausted resources and still not helped
| WrongHelp //i.e. caller offered smoking cessation counseling when caller needed sex trafficking aftercare
| NotHelped of Followup
| GivenReferral of ReferredToNextNgo
and ReferredToNextNgo = ReferredToNextNgo of Followup * Ngo
type CallOutcome =
| CallerHelped
| CallerNotHelped of Followup
| CallerReferred of ReferredToNextNgo
type Call = Call of Caller * CallerRequest * CallOutcome
And here is the error I'm getting:
C:\Users\3CU1501060\Documents\Projects\DUandTypesPractice\DUandTypesPractice\TerminalBuilder.fs(27,27): Warning FS0025: Incomplete pattern matches on this expression. For example, the value '"a"' may indicate a case not covered by the pattern(s). (FS0025) (DUandTypesPractice)
when you pattern match
let sn =
match answer.Trim().ToLower() with
| "1" -> Some LearningDisabled
| "2" -> Some PhysicallyDisabled
| "3" -> Some MentalIllness
| "4" -> Some SubstanceAddiction
| "5" -> Some Pregnancy
| "6" -> Some ChronicIllness
| "7" -> Some Undiagnosed
| "exit" -> printfn "No disabling conditions"
None
```
you check "1", "2", ... "exit", but there are other values, for example "a", you need to add another case
| answer -> //do something
in your case maybe
| answer -> printfn "not supported answer %A" answer
None // or retry?
the compiler is helping you, telling you "what happen if user choose 'a'"?

In F#, How can I attach metadata to discriminated union values?

I want to create something that's kind of like an enum with an F# record type for a value instead of an int. For example, if I've got the union:
type BologneseIngredients = | Spaghetti
| Tomatoes
| MincedBeef
| GrandmasSecretIngredient
I know that spaghetti is always 30cm long and tomatoes are always red. What I could do is have a 'get metadata' function:
let getMetadata = function
| Spaghetti -> { length: 30.0<cm> }
| Tomatoes -> { colour: Color.Red }
| _ -> { }
but I'd really like to keep the definition of the union and the data together. Is there a nice way to do this?
You could add properties to your discriminated union...
type BologneseIngredients =
| Spaghetti
| Tomatoes
| MincedBeef
| GrandmasSecretIngredient
member x.Color =
match x with
| Spaghetti -> Color.AntiqueWhite
| Tomatoes -> Color.Red
| MincedBeef -> Color.Firebrick
| GrandmasSecretIngredient -> Color.Transparent
let foo = Tomatoes
printfn "%A" foo.Color
> Color [Red]
my suggestion:
module Recipes =
type BologneseIngredients = | Spaghetti
| Tomatoes
| MincedBeef
| GrandmasSecretIngredient
let length (ind : BologneseIngredients) : float<cm> option =
match ind with
| Sphaghetti -> Some 30.0<cm>
| _ -> None
// .. or a bit more "metadata"ish
type Metadata =
| Length of float<cm>
| Color of System.Drawing.Color
let metadata =
function
| Sphaghetti -> [ Length 30.0<cm ]
| Tomatoes -> [ Color System.Drawing.Color.Red ]
| ...
let metaLength meta =
meta |> List.tryPick (function | Length l -> Some l | _ -> None)
let getLength = metadata >> metaLength

URL BNF search part does not make sense

While implementing a Java regular expression for URL based on the URL BNF published by W3C, I've failed to understand the search part. As quoted:
httpaddress h t t p : / / hostport [ / path ] [ ?
search ]
search xalphas [ + search ]
xalphas xalpha [ xalphas ]
xalpha alpha | digit | safe | extra | escape
alpha a | b | c | d | e | f | g | h | i | j | k |
l | m | n | o | p | q | r | s | t | u | v |
w | x | y | z | A | B | C | D | E | F | G |
H | I | J | K | L | M | N | O | P | Q | R |
digit 0 |1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
safe $ | - | _ | # | . | & | + | -
extra ! | * | " | ' | ( | ) | ,
Search claims it is xalphas seperated by a plus sign.
xalphas can contain plus signs by it self, as claimed by safe.
Thus according to my understanding , it should be:
search xalphas
Where am I wrong here?
That's pretty clearly a mistake (+ is a reserved delimiter for URIs), but the BNF you're linking to seems to be out of date. Probably best to use the one included at the end of the latest RFC 3986.

Resources