F# Sequences and Records - f#

I have 2 sequences...
type Suit = Spades | Clubs | Hearts | Diamonds
type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King
type Card = { suit: Suit; rank: Rank}
and intValueCard = {rank: Rank; value: int} // translates the union into an actual int
and just wondering how I can get the Card's Rank in an actual int... so far I have
let getActualValue (card:Card) =
value |> translatedValue.Rank
but for the life of me I can't figure out how to deal with a sequence and getActualValue doesn't work..

I don't see any sequences. You have Suit and Rank which are discriminated unions, and you have Card which is a record. Not sure what you meant by intValueCard = {rank: Rank; value: int}, and getActualValue refers to a translatedValue which isn't explained. What will the integer value from the rank be used for? You can possibly get better help if you edit and improve your question.
Let's assume you want the rank in order to calculate the advantage in a game. It is probably best to create a function like this.
let weightFromRank rank =
match rank with
| Ace -> 1
| Two -> 2
...etc...
You can use the function keyword to make a less verbose version of this function.
I believe it is not a good idea to use an enum, because you will miss out on important advantages of functional programming. Enum is a .NET type, and not a functional type.
Different kinds of games have different kind of weights on Ace. Some games give Ace a weight of 14, one above the King. You can then have different functions for calculating the weight, depending on what kind of game is played.
Take the following advice with a grain of salt, since I'm not a top notch expert on F#. A different approach would be to put the weight as a separate field in a record or a discriminated union or something like that. This approach I believe is less efficient, because the weight follows from the rank, so you would effectively be duplicating information in places where it's not needed, thereby also making your code more difficult to understand. It would also be less efficient to handle different weights for different kinds of games.

You can declare Rank as a enum:
type Rank =
| Ace = 1
| Two = 2
| Three = 3
....
then use int to get the underlying value:
let getActualValue ({rank = r}) = int r

If you want the integer rank for comparison with other ranks, then you can just compare the discriminated union values instead, as comparison is built into them for free:
Eight < Nine // true
Jack < Six // false
[Seven; Ace; Four; Two] |> List.sort
// [Ace; Two; Four; Seven]
Now, if you really need the integer rank value for some reason you could use reflection to get the DU cases. Just make sure that you that you do it inside a top level module value, not inside a function, so that the reflection is only done once when the program starts:
open FSharp.Reflection
let ranks =
FSharpType.GetUnionCases(typeof<Rank>)
|> Array.map (fun c -> FSharpValue.MakeUnion(c, [||]) :?> Rank)
let getActualValue rank = Array.findIndex ((=) rank) ranks
getActualValue Ace // 0
getActualValue Two // 1
getActualValue King // 12

Related

Modeling domain type

A limit price has a decimal value. A Market price does not.
How do I model this in F#?
module TradingDomain
let NoPrice = None
type PriceActionType =
| Limit of decimal
| Market of NoPrice
You can just not give Market any arguments:
type PriceActionType =
| Limit of decimal
| Market
There are a couple of ways to go about it, but if you do domain modelling it's a good idea to have an understanding of all the components, in this case, 1) how traders think about the order, 2) how FIX (if that's what's being used) thinks about the order, and 3) how the market you trade thinks about the order. Btw, there's this book that you might find useful. Also, Chapter 7 in F# Deep Dives.
That said Tarmil's answer should work for you, and here but I have two comments. Sometimes it's better to be explicit about the type and use .NET types. float and decimal are F# aliases and they might refer to the function that casts to float. There is also the possibility to use Some and None for expressing the price. So here's a version that includes the orderside as well:
type Price =
| Limit of Decimal
| Market
type OrderSide =
| Buy of Price
| Sell of Price
| ShortSell of Price
You can use it like this: Buy (Limit 10.0M) or Sell Market.
You could also define Price like this:
type Price2 =
| Limit of Decimal option
| None
Whichever version will help you later do validation.

How do functional programmers test functions that return a unit?

How do functional programmers test functions that return a unit?
In my case, I believe I need to unit test an interface to this function:
let logToFile (filePath:string) (formatf : 'data -> string) data =
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(formatf data)
data
What is the recommended approach when I'm unit testing a function with I/O?
In OOP, I believe a Test Spy can be leveraged.
Does the Test Spy pattern translate to functional programming?
My client looks something like this:
[<Test>]
let ``log purchase``() =
[OneDollarBill] |> select Pepsi
|> logToFile "myFile.txt" (sprintf "%A")
|> should equal ??? // IDK
My domain is the following:
module Machine
type Deposit =
| Nickel
| Dime
| Quarter
| OneDollarBill
| FiveDollarBill
type Selection =
| Pepsi
| Coke
| Sprite
| MountainDew
type Attempt = {
Price:decimal
Need:decimal
}
type Transaction = {
Purchased:Selection
Price:decimal
Deposited:Deposit list
}
type RequestResult =
| Granted of Transaction
| Denied of Attempt
(* Functions *)
open System
let insert coin balance = coin::balance
let refund coins = coins
let priceOf = function
| Pepsi
| Coke
| Sprite
| MountainDew -> 1.00m
let valueOf = function
| Nickel -> 0.05m
| Dime -> 0.10m
| Quarter -> 0.25m
| OneDollarBill -> 1.00m
| FiveDollarBill -> 5.00m
let totalValue coins =
(0.00m, coins) ||> List.fold (fun acc coin -> acc + valueOf coin)
let logToFile (filePath:string) (formatf : 'data -> string) data =
let message = formatf data
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
data
let select item deposited =
if totalValue deposited >= priceOf item
then Granted { Purchased=item
Deposited=deposited
Price = priceOf item }
else Denied { Price=priceOf item;
Need=priceOf item - totalValue deposited }
Do not see this as an authoritative answer, because I'm not an expert on testing, but my answer to this question would be that, in a perfect world, you cannot and do not need to test unit-returning functions.
Ideally, you would structure your code so that it is composed from some IO to read data, transformations encoding all the logic and some IO to save the data:
read
|> someLogic
|> someMoreLogic
|> write
The idea is that all your important things are in someLogic and someMoreLogic and that read and write are completely trivial - they read file as string or sequence of lines. This is trivial enough that you do not need to test it (now, you could possibly test the actual file writing by reading the file back again, but that's when you want to test the file IO rather than any logic that you wrote).
This is where you would use a mock in OO, but since you have a nice functional structure, you would now write:
testData
|> someLogic
|> someMoreLogic
|> shouldEqual expectedResult
Now, in reality, the world is not always that nice and something like a spy operation ends up being useful - perhaps because you are interoperating with a world that is not purely functional.
Phil Trelford has a nice and very simple Recorder that lets you record calls to a function and check that it has been called with the expected inputs - and this is something I've found useful a number of times (and it is simple enough that you do not really need a framework).
Obviously, you could use a mock as you would in imperative code as long as the unit of code takes its dependencies as a parameter.
But, for another approach, I found this talk really interesting Mocks & stubs by Ken Scambler. As far as I recall the general argument was that you should avoid using mocks by keeping all functions as pure as possible, making them data-in-data-out. At the very edges of your program, you would have some very simple functions that perform the important side-effects. These are so simple that they don't even need testing.
The function you provided is simple enough to fall into that category. Testing it with a mock or similar would just involve ensuring that certain methods are called, not that the side-effect occurred. Such a test isn't meaningful and doesn't add any value over the code itself, while still adding a maintenance burden. It's better to test the side-effect part with an integration test or end-to-end test that actually looks at the file that was written.
Another good talk on the subject is Boundaries by Gary Bernhardt which Discusses the concept of Functional Core, Imperative Shell.

Comparing discriminated union cases with < and > in F#

I'm learning F# and I am building a quick set of functions which compare two poker hands and determine the winner.
I made this discriminated union to represent categories of poker hands:
type Category =
| HighCard
| OnePair
| TwoPair
| ThreeOfAKind
| Straight
| Flush
| FullHouse
| FourOfAKind
| StraightFlush
I use this code to compare categories to determine if one hand is better than another:
if playerCategory > houseCategory then Win
elif playerCategory < houseCategory then Loss
// ... More code to handle cases within the same category
So, for example, the expression:
let playerCategory = FullHouse
let houseCategory = HighCard
if playerCategory > houseCategory then Win
elif playerCategory < houseCategory then Loss
// ... Other code
Would have the value Win.
However, I don't understand how the < and > operators are able to work here. (Originally I had a function which mapped each case to a numeric value, but I realized it wasn't necessary.) If I rearrange the order of the cases then the logic breaks, so I'm assuming each case is assigned some default value corresponding to its order within the type?
But I would definitely appreciate a bit more insight...
This is described in the specification:
by default, record, union, and struct type definitions called
structural types implicitly include compiler-generated declarations
for structural equality, hashing, and comparison. These implicit
declarations consist of the following for structural equality and
hashing
8.15.4 Behavior of the Generated CompareTo implementations
If T is a union type, invoke Microsoft.FSharp.Core.Operators.compare
first on the index of the union cases for the two values, and then on
each corresponding field pair of x and y for the data carried by the
union case. Return the first non-zero result.
In addition to what Lee said, there's also in the spec
8.5.4 Compiled Form of Union Types for Use from Other CLI Languages
A compiled union type U has:
...
One CLI instance property U.Tag for each case C. This property fetches or computes an integer tag corresponding to the case.
The compiler-generated CompareTo method uses the backing fields of these properties to determine the index as stipulated in 8.15.4. This is evidenced by IlSpy:
int tag = this._tag;
int tag2 = category._tag;
if (tag != tag2)
{
return tag - tag2;
}
if (this.Tag != 0)
{
return 0;
}

How do I check whether a variable is an integer in F#?

I'm new in F#.
How do I check whether a variable is an integer or another type.
Thanks.
One way is listed by #ildjarn in the comments:
let isInt x = box x :? int
An idiomatic way would be to use pattern matching. First, define a discriminated union which defines the possible options:
type Test =
| IsAnInteger of int
| IsADouble of double
| NotANumber of Object
then use a match statement to determine which option you got. Note that when you initially create the value you wish to use with a match statement, you need to put it into the discriminated union type.
let GetValue x =
match x with
| IsAnInteger(a) -> a
| IsADouble(b) -> (int)b
| NotAnInteger(_) -> 0
Since you're probably going to use your test to determine control flow, you might as well do it idiomatically. This can also prevent you from missing cases since match statements give you warnings if you don't handle all possible cases.
>GetValue (NotAnInteger("test"));;
val it : int = 0
>GetValue (IsADouble(3.3))
val it : int = 3
>GetValue (IsAnInteger(5))
val it : int = 5
Considering that you tagged this question "c#-to-f#" I'm assuming you're coming to F# from a C# background. Therefore I think you may be a bit confused by the type inference since you're probably used to explicitly typing variables.
You can explicitly declare the type of a value if you need to.
let x:int = 3
But it's usually easier and better to let the type inference do this work for you. You'll note that I said value--the declaration above is not a variable because you cannot do a destructive assignment to it. If you want a variable then do this:
let mutable x:int = 3
You can then assign a new value to x via this construct
x <- 5
But, as a rule, you'll want to avoid mutable values.

Transform an Abstract Syntax Tree (AST) in F#

I am trying to design an AST for a decision logic table. One of the things I would like to be able to do with the discriminated union that represents my AST is transform parts of it for different reasons. For clarity I will give you an example
Decision Logic Table
# VAR = 10 ;Y;
The above can be read as there is one rule and the condition VAR = 10 enters this rule with a Y entry.
Abstract Syntax Tree Definition (simplified for this example)
type expression =
| Value of double
| Variable of string
| Equality of expression * expression
type entry =
| Entry of string
type entries =
| Entries of entry list
type conditional =
| ConditionEntries of expression * entries
type condition
| Condition of expression * string
type rule =
| Rule of condition list
Rendered (before transform)
ConditionEntries(
Equality(
Variable("VAR"),
Value(10.0)),
Entries(["Y"]))
Rendered (after transform)
Rule(
Condition(
Equality(
Variable("VAR"),
Value(10.0)
),
Entry("Y")
)
)
Now what I would like to do is transform the above tree to expand the rules that are represented in the entries. My thinking was I could use a recursive function and pattern-matching to do this but I am having a little trouble wrapping my head around it right now.
I guess in essence what I am trying to do is whenever I see a ConditionEntries node, I want to emit a new Rule for every string in the Entries list where the Condition is combined with the Entry. Does that make any sense?
Thanks in advance for any advice.
p.s. I haven't quite tried to compile the above example, so please forgive any grammatical errors.
Hmm, based on your AST, which is awfully broken up, here is a tranform function which produces the output from input you desire (though it's not recursive, just uses List.map with some pattern matching. expression is your only recursive type but it doesn't look like you want to process it recursively?):
let ex1 =
ConditionEntries(
Equality(
Variable("VAR"),
Value(10.0)),
Entries([Entry("Y")]))
let ex2 =
ConditionEntries(
Equality(
Variable("VAR"),
Value(10.0)),
Entries([Entry("X");Entry("Y");Entry("Z")]))
let transform ces =
match ces with
| ConditionEntries(x, Entries(entries)) ->
entries
|> List.map (function Entry(entry) -> Condition(x, entry))
//FSI output:
> transform ex1;;
val it : condition list =
[Condition (Equality (Variable "VAR",Value 10.0),"Y")]
> transform ex2;;
val it : condition list =
[Condition (Equality (Variable "VAR",Value 10.0),"X");
Condition (Equality (Variable "VAR",Value 10.0),"Y");
Condition (Equality (Variable "VAR",Value 10.0),"Z")]

Resources