CodeWars.com Kata : Categorize New Member - f#

Kata Description:
The Western Suburbs Croquet Club has two categories of membership, Senior and Open. They would like your help with an application form that will tell prospective members which category they will be placed.
To be a senior, a member must be at least 55 years old and have a handicap greater than 7. In this croquet club, handicaps range from -2 to +26; the better the player the lower the handicap.
Input
Input will consist of a list of lists containing two items each. Each list contains information for a single potential member. Information consists of an integer for the person's age and an integer for the person's handicap.
Example Input
[[18, 20],[45, 2],[61, 12],[37, 6],[21, 21],[78, 9]]
Output
Output will consist of a list of string values (in Haskell: Open or Senior) stating whether the respective member is to be placed in the senior or open category.
Example Output
["Open", "Open", "Senior", "Open", "Open", "Senior"]
I have solved this Answer in three different languages: Python, C#, and finally JavaScript, my code is below.
C#:
using System;
using System.Collections.Generic;
using System.Linq;
public class Kata
{
public static IEnumerable<string> OpenOrSenior(int[][] data) => data.Select(x => { return (x[0] >= 55 && x[1] > 7) ? "Senior" : "Open"; });
}
Python:
def openOrSenior(array): return [ "Senior" if (x[0] >= 55 and x[1] > 7) else "Open" for x in array]
JavaScript:
function openOrSenior(data) { return data.map(x => { if(x[0] >= 55 && x[1] > 7){return "Senior";}else{return "Open";} }); }
I'm having trouble though solving this problem in F#...
I'm new to F#, I have Fuchu tests' already written out.
I need some help on some changes I should make to my F# code if possible.
F#:
The function parameter needs to take a 2D array.
let OpenOrSenior _ =
let mutable _list : List<string> = []
let mutable _val : string = ""
for i in _ do
_val <- if i.[0] >= 55 && i.[1] > 7 then "Senior" else "Open"
_list <- _val :: _list
Please let me know what you think.
Thanks in advance.

I tweaked your mutable version to get it working. The last line reverses the list to get the order right:
let openOrSenior (input:int list list) =
let mutable _list : List<string> = []
let mutable _val : string = ""
for i in input do
_val <- if i.[0] >= 55 && i.[1] > 7 then "Senior" else "Open"
_list <- _val :: _list
_list |> List.rev
However use of the mutable keyword is a sign of code smell. Here is a more functional version:
let openOrSenior =
List.map
(function
|age::[hcp] when age >= 55 && hcp > 7 -> "Senior"
|_ -> "Open")
Note: You need to replace , with ; in your input. Comma's are used for Tuple's in F#.

As was suggested by the comments fsharpforfunandprofit, but also F# wiki and the MS docs are all great. For more open ended questions just drop by the F# Slack.
There are a couple of points, first, the domain would be much better modelled, by a list of tuples, or a record, then by a list of lists. Also Open or Senior should be modelled by a Discriminated Union. That way you could pattern match for most idiomatic and type safe code. However you can simply rewrite your function to take a list of lists, and map a function over it, just like you do in your other examples:
let ageAndHandi = [[18; 20];[45; 2];[61; 12];[37; 6];[21; 21];[78; 9]]
let openOrSenior (xs:List<List<int>>) =
xs
|> List.map
(fun (x:List<int>) -> if x.[0] >= 55 && x.[1] > 7 then "Senior" else "Open")
openOrSenior ageAndHandi //val it : string list = ["Open"; "Open"; "Senior"; "Open"; "Open"; "Senior"]
There are two ways to specify the type in F#, the .NET (List<List<int>>) and ML int list list. Either way is fine. However the preferred way is to avoid type annotations, let the type inference do its magic, and make the code as generic as possible. So you don't need to annotate the list at all.
As I said you can also do this with a for comprehension, which should be very readable even if you don't know F#:
let openOrSenior2 xs =
[for (x:List<int>) in xs do
if x.[0] >= 55 && x.[1] > 7 then yield "Senior" else yield "Open"]
openOrSenior2 ageAndHandi
And here is the version that actually models the domain, and uses pattern matching:
//record to describe a club member
type ClubMember = {
age: int
handi: int
}
//Discriminated Union to describe possible sub-types of club member
type MemberType = Open | Senior
//list of club members
let ageAndHandi2 = [{age=18;handi=20}
{age=45;handi=2}
{age=61;handi=12}]
//function to return the type of club member, notice that it's not a string
//but you could do that as well
let selectMember (mem:ClubMember) =
match mem with
| x when (mem.age >= 55) && (mem.handi > 7) -> Senior
| _ -> Open
//pipe the member list into the selection function, which return a MemberType List
ageAndHandi2
|> List.map selectMember
//val it : MemberType list = [Open; Open; Senior]

" Categorize New Member "
JavaSvcript code using map and ternary operator.
function openOrSenior(data){
return data.map( x => x[0] >= 55 && x[1] > 7 ? "Senior" : "Open");
}
console.log(openOrSenior([[45, 12],[55,21],[19, -2],[104, 20]])); //,['Open', 'Senior', 'Open', 'Senior'])
console.log(openOrSenior([[3, 12],[55,1],[91, -2],[54, 23]])); //,['Open', 'Open', 'Open', 'Open'])
console.log(openOrSenior([[59, 12],[55,-1],[12, -2],[12, 12]])); //,['Senior', 'Open', 'Open', 'Open'])

function openOrSenior(data){
return data.map(dig => (dig[0] >= 55 && dig[1] > 7 ? 'Senior' : 'Open'));
}

Related

Thoth.Json.Net conditional parsing

I have a JSON document that I'm parsing using Thoth.Json.Net. The document has an array containing a set of objects that each have a "type" attribute with a value that identifies their type. Each of these types needs a different decoder so I need to be able to provide some sort of filter based on the value of the "type" attribute. How can I do this?
Update:
After getting the "hack" that I describe above working, I revisited using the CE and decodeByType custom decoder, with each decoder returning a value from a Discriminated Union as mentioned by #tranquillity above. Once I had got my head around all the types the only thing I had to do was to specify the types for the Builder:
Builder: type DecoderBuilder () =
member __.Bind((decoder:Decoder<'a>), (func:('a -> Decoder<'b>))) =
Decode.andThen func decoder
This enabled the use of the CE to combine decoders easily as described by #brianberns below. I created a new file for the custom decoders and the Discriminated Union and found that I was able to extract the values from the JSON more closely to the domain model (making unrepresentable state impossible because an error will be returned if the JSON structure is invalid).
All in all cleaner, more functional, and elegant code. Thank you for the help.
I'm not a Thoth expert, but here's what I'd do. First, I find it easier to combine decoders using a computation expression:
type DecodeBuilder() =
member _.Bind(decoder, f) : Decoder<_> =
Decode.andThen f decoder
member _.Return(value) =
Decode.succeed value
member _.ReturnFrom(decoder : Decoder<_>) =
decoder
let decode = DecodeBuilder()
Then I invented two custom decoders, just as examples, and put them in a map by name. One reverses a string, and one decodes using the ROT13 cipher. Of course, you'll use your own custom decoders here instead:
let decodeReverse =
decode {
let! str = Decode.string
return str
|> Seq.rev
|> Seq.toArray
|> String
}
let decodeRot13 =
let rot13 c =
if 'a' <= c && c <= 'm' || 'A' <= c && c <= 'M' then
char (int c + 13)
elif 'n' <= c && c <= 'z' || 'N' <= c && c <= 'Z' then
char (int c - 13)
else c
decode {
let! str = Decode.string
return str
|> Seq.map rot13
|> Seq.toArray
|> String
}
let customDecoders =
Map [
"Reverse", decodeReverse
"Rot13", decodeRot13
]
Then, custom decoding is just a matter of decoding the "type" field, looking up the corresponding custom decoder, and using it to decode the "value" field:
let decodeByType =
decode {
let! typ = Decode.field "type" Decode.string
return! Decode.field "value" customDecoders.[typ]
}
Example usage:
Decode.fromString
(Decode.array decodeByType)
"""
[
{
"type" : "Reverse",
"value" : "edcba"
},
{
"type" : "Rot13",
"value" : "qrpbqr guvf"
}
]
"""
|> printfn "%A" // Ok [|"abcde"; "decode this"|]
I put the complete program here for reference.

F# why does string conversion fail with underscores

Is there any particular reason why piping to int works here but the system convert doesn't? Which method should be used?
printfn "%i" ("1_2" |> int)
printfn "%i" (System.Int32.Parse("1_2"))
I am using .NET core 2.2
It looks like the first method calls
FSharp.Core.dll!Microsoft.FSharp.Core.LanguagePrimitives.ParseInt32(string s)
and the second calls
System.Private.CoreLib.dll!int.Parse(string s)
So if anyone is curious, I looked at the difference. the .NET core dll doesnt strip underscores
System.Private.CoreLib.dll uses
private static unsafe void StringToNumber(ReadOnlySpan<char> str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
Debug.Assert(info != null);
fixed (char* stringPointer = &MemoryMarshal.GetReference(str))
{
char* p = stringPointer;
if (!ParseNumber(ref p, p + str.Length, options, ref number, info, parseDecimal)
|| (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer))))
{
throw new FormatException(SR.Format_InvalidString);
}
}
}
And FSharp.Core.dll uses
let ParseInt32 (s:string) =
if System.Object.ReferenceEquals(s,null) then
raise( new System.ArgumentNullException("s") )
let s = removeUnderscores (s.Trim())
let l = s.Length
let mutable p = 0
let sign = getSign32 s &p l
let specifier = get0OXB s &p l
if p >= l then formatError() else
match Char.ToLowerInvariant(specifier) with
| 'x' -> sign * (int32OfUInt32 (Convert.ToUInt32(UInt64.Parse(s.Substring(p), NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture))))
| 'b' -> sign * (int32OfUInt32 (Convert.ToUInt32(parseBinaryUInt64 (s.Substring(p)))))
| 'o' -> sign * (int32OfUInt32 (Convert.ToUInt32(parseOctalUInt64 (s.Substring(p)))))
| _ -> Int32.Parse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture)
As others said two different implementations of parsing an integer is used and doesn't necessarily produce the same result. However, one might wonder why F# allows 1_2 as a valid int?
I browsed the history of the source code and found that it was implemented in this commit: implement Underscore Literals
It was made to support literals in F# like this:
let x = 1_000_000
let y = 1000000
x = y // true
x and y is equal but 1_000_000 is thanks to the underscores somewhat easier to read as 1 million.
Because how it was implemented it also leaked into runtime as now int "1_000_000" parse successfully.
In the first case ("1_2" |> int) you are using int which is an F# primitive.
In the second case (System.Int32.Parse("1_2")) you are using System.Int32 which is a .NET CLR and not specifically an F# type.
The two use different rules for parsing integers as you discovered in the implementations.

change properties of an element in a set and put it back in the set

Here's the problem,
Suppose we have a datatype, and a set of the datatype:
data Color=red(int n, str name)|black(int n, str name);
set[Color] coloredBalls={red(1,"a"), red(2,"b")};
I would like to iterate through the elements of the set and change the elements as follows:
for(Color aColor <- coloredBalls)
{
if(aColor.n == 2)
aColor.str="bb"
//I would like to change the node: red(2,"b") to red(2,"bb") in the set coloredBalls
//but am unable to express it in Rascal, unless I recourse to using a "Map", which I
//think obfuscates the code quite a bit. Maybe using switch/visit with case does the trick?
}
There are many ways to build the new set you want to have (you can't actually change the existing set of course).
You can use visit:
coloredBalls = visit (coloredBalls) {
case red(a,b) => red(a, b + "b")
}
Or use a comprehension with an is:
coloredBalls = { x is red ? x[name=name+"b"] : x | x <- coloredBalls};
Or with pattern match on the generator side:
coloredBalls = {red(a, b + "b") | red(a,b) <- coloredBalls} + { y | y <- coloredBalls, !(y is red)};
Or with a pattern match on the insert side of the comprehension:
coloredBalls = {red(a,b) := c ? red(a,b+"b") : c | c <- coloredBalls};

Project new values from existing value

I'm writing my very first F# program, the aim being simply to learn F#.
What I want to is provide a list of dates, and attributes (e.g.DayOfWeek, DayOfMonth) of those dates. I have managed to provide the list of dates and I know that the .net Framework gives me everything I need to extract all the attributes, I just can't figure out how to add the attribute as new columns in my list.
Here's what I have so far:
type Span = Span of TimeSpan with
static member (+) (d:DateTime, Span wrapper) = d + wrapper //this is defining the + operator
static member Zero = Span(new TimeSpan(0L))
type Dates() =
let a = DateTime.Parse("01/12/2013")
let b =DateTime.Parse("02/12/2013")
let ts = TimeSpan.FromDays(1.0)
member this.Get() = [a .. Span(ts) .. b]
let mydates = new Dates()
mydates.Get()
When I run that code I get a list of DateTime values, with 2 records in the list. I can now do something like this:
mydates.Get() |> List.map (fun x -> x.DayOfWeek);;
which returns:
val it : DayOfWeek list = [Sunday; Monday]
or
mydates.Get() |> List.map (fun x -> x.DayOfYear);;
which returns:
val it : int list = [335; 336]
That's all great, however what I would like to do is project a list that has 2 "columns" (if columns is the right word) so that my output is (something like):
val it : int list = [(Sunday,335); (Monday,336)]
I hope that explains what I'm after.
thanks
Jamie
For your example, the solution is simple, make the map return a tuple like so
mydates.Get() |> List.map (fun x -> x.DayOfWeek,x.DayOfYear);;

F# curried function

Anyone have a decent example, preferably practical/useful, they could post demonstrating the concept?
(Edit: a small Ocaml FP Koan to start things off)
The Koan of Currying (A koan about food, that is not about food)
A student came to Jacques Garrigue and said, "I do not understand what currying is good for." Jacques replied, "Tell me your favorite meal and your favorite dessert". The puzzled student replied that he liked okonomiyaki and kanten, but while his favorite restaurant served great okonomiyaki, their kanten always gave him a stomach ache the following morning. So Jacques took the student to eat at a restaurant that served okonomiyaki every bit as good as the student's favorite, then took him across town to a shop that made excellent kanten where the student happily applied the remainder of his appetite. The student was sated, but he was not enlightened ... until the next morning when he woke up and his stomach felt fine.
My examples will cover using it for the reuse and encapsulation of code. This is fairly obvious once you look at these and should give you a concrete, simple example that you can think of applying in numerous situations.
We want to do a map over a tree. This function could be curried and applied to each node if it needs more then one argument -- since we'd be applying the one at the node as it's final argument. It doesn't have to be curried, but writing another function (assuming this function is being used in other instances with other variables) would be a waste.
type 'a tree = E of 'a | N of 'a * 'a tree * 'a tree
let rec tree_map f tree = match tree with
| N(x,left,right) -> N(f x, tree_map f left, tree_map f right)
| E(x) -> E(f x)
let sample_tree = N(1,E(3),E(4)
let multiply x y = x * y
let sample_tree2 = tree_map (multiply 3) sample_tree
but this is the same as:
let sample_tree2 = tree_map (fun x -> x * 3) sample_tree
So this simple case isn't convincing. It really is though, and powerful once you use the language more and naturally come across these situations. The other example with some code reuse as currying. A recurrence relation to create prime numbers. Awful lot of similarity in there:
let rec f_recurrence f a seed n =
match n with
| a -> seed
| _ -> let prev = f_recurrence f a seed (n-1) in
prev + (f n prev)
let rowland = f_recurrence gcd 1 7
let cloitre = f_recurrence lcm 1 1
let rowland_prime n = (rowland (n+1)) - (rowland n)
let cloitre_prime n = ((cloitre (n+1))/(cloitre n)) - 1
Ok, now rowland and cloitre are curried functions, since they have free variables, and we can get any index of it's sequence without knowing or worrying about f_recurrence.
While the previous examples answered the question, here are two simpler examples of how Currying can be beneficial for F# programming.
open System.IO
let appendFile (fileName : string) (text : string) =
let file = new StreamWriter(fileName, true)
file.WriteLine(text)
file.Close()
// Call it normally
appendFile #"D:\Log.txt" "Processing Event X..."
// If you curry the function, you don't need to keep specifying the
// log file name.
let curriedAppendFile = appendFile #"D:\Log.txt"
// Adds data to "Log.txt"
curriedAppendFile "Processing Event Y..."
And don't forget you can curry the Printf family of function! In the curried version, notice the distinct lack of a lambda.
// Non curried, Prints 1 2 3
List.iter (fun i -> printf "%d " i) [1 .. 3];;
// Curried, Prints 1 2 3
List.iter (printfn "%d ") [1 .. 3];;
Currying describes the process of transforming a function with multiple arguments into a chain of single-argument functions. Example in C#, for a three-argument function:
Func<T1, Func<T2, Func<T3, T4>>> Curry<T1, T2, T3, T4>(Func<T1, T2, T3, T4> f)
{
return a => b => c => f(a, b, c);
}
void UseACurriedFunction()
{
var curryCompare = Curry<string, string, bool, int>(String.Compare);
var a = "SomeString";
var b = "SOMESTRING";
Console.WriteLine(String.Compare(a, b, true));
Console.WriteLine(curryCompare(a)(b)(true));
//partial application
var compareAWithB = curryCompare(a)(b);
Console.WriteLine(compareAWithB(true));
Console.WriteLine(compareAWithB(false));
}
Now, the boolean argument is probably not the argument you'd most likely want to leave open with a partial application. This is one reason why the order of arguments in F# functions can seem a little odd at first. Let's define a different C# curry function:
Func<T3, Func<T2, Func<T1, T4>>> BackwardsCurry<T1, T2, T3, T4>(Func<T1, T2, T3, T4> f)
{
return a => b => c => f(c, b, a);
}
Now, we can do something a little more useful:
void UseADifferentlyCurriedFunction()
{
var curryCompare = BackwardsCurry<string, string, bool, int>(String.Compare);
var caseSensitiveCompare = curryCompare(false);
var caseInsensitiveCompare = curryCompare(true);
var format = Curry<string, string, string, string>(String.Format)("Results of comparing {0} with {1}:");
var strings = new[] {"Hello", "HELLO", "Greetings", "GREETINGS"};
foreach (var s in strings)
{
var caseSensitiveCompareWithS = caseSensitiveCompare(s);
var caseInsensitiveCompareWithS = caseInsensitiveCompare(s);
var formatWithS = format(s);
foreach (var t in strings)
{
Console.WriteLine(formatWithS(t));
Console.WriteLine(caseSensitiveCompareWithS(t));
Console.WriteLine(caseInsensitiveCompareWithS(t));
}
}
}
Why are these examples in C#? Because in F#, function declarations are curried by default. You don't usually need to curry functions; they're already curried. The major exception to this is framework methods and other overloaded functions, which take a tuple containing their multiple arguments. You therefore might want to curry such functions, and, in fact, I came upon this question when I was looking for a library function that would do this. I suppose it is missing (if indeed it is) because it's pretty trivial to implement:
let curry f a b c = f(a, b, c)
//overload resolution failure: there are two overloads with three arguments.
//let curryCompare = curry String.Compare
//This one might be more useful; it works because there's only one 3-argument overload
let backCurry f a b c = f(c, b, a)
let intParse = backCurry Int32.Parse
let intParseCurrentCultureAnyStyle = intParse CultureInfo.CurrentCulture NumberStyles.Any
let myInt = intParseCurrentCultureAnyStyle "23"
let myOtherInt = intParseCurrentCultureAnyStyle "42"
To get around the failure with String.Compare, since as far as I can tell there's no way to specify which 3-argument overload to pick, you can use a non-general solution:
let curryCompare s1 s2 (b:bool) = String.Compare(s1, s2, b)
let backwardsCurryCompare (b:bool) s1 s2 = String.Compare(s1, s2, b)
I won't go into detail about the uses of partial function application in F# because the other answers have covered that already.
It's a fairly simple process. Take a function, bind one of its arguments and return a new function. For example:
let concatStrings left right = left + right
let makeCommandPrompt= appendString "c:\> "
Now by currying the simple concatStrings function, you can easily add a DOS style command prompt to the front of any string! Really useful!
Okay, not really. A more useful case I find is when I want to have a make a function that returns me data in a stream like manner.
let readDWORD array i = array[i] | array[i + 1] << 8 | array[i + 2] << 16 |
array[i + 3] << 24 //I've actually used this function in Python.
The convenient part about it is that rather than creating an entire class for this sort of thing, calling the constructor, calling obj.readDWORD(), you just have a function that can't be mutated out from under you.
You know you can map a function over a list? For example, mapping a function to add one to each element of a list:
> List.map ((+) 1) [1; 2; 3];;
val it : int list = [2; 3; 4]
This is actually already using currying because the (+) operator was used to create a function to add one to its argument but you can squeeze a little more out of this example by altering it to map the same function of a list of lists:
> List.map (List.map ((+) 1)) [[1; 2]; [3]];;
val it : int list = [[2; 3]; [4]]
Without currying you could not partially apply these functions and would have to write something like this instead:
> List.map((fun xs -> List.map((fun n -> n + 1), xs)), [[1; 2]; [3]]);;
val it : int list = [[2; 3]; [4]]
I gave a good example of simulating currying in C# on my blog. The gist is that you can create a function that is closed over a parameter (in my example create a function for calculating the sales tax closed over the value of a given municipality)out of an existing multi-parameter function.
What is appealing here is instead of having to make a separate function specifically for calculating sales tax in Cook County, you can create (and reuse) the function dynamically at runtime.

Resources