F# Pattern Match on Seq.Length - f#

I'm learning some F# and messing around with pattern matching. I have the below code.
Seq.distinct [1; 1; 2]
|> match Seq.length with
| 1 -> printf "one"
| 2 -> printf "two"
| _ -> printf "other"
But when running or trying to compile it gives the error of:
This expression was expected to have type
'a -> int
but here has type
int
I'm not quite sure what the issue is and what exactly is being asked. I'm sure I'm missing something simple, but is there another way I should be doing this?

You could do either this:
match Seq.distinct [1; 1; 2] |> Seq.length with
| 1 -> printf "one"
| 2 -> printf "two"
| _ -> printf "other"
or this:
Seq.distinct [1; 1; 2]
|> Seq.length
|> function
| 1 -> printf "one"
| 2 -> printf "two"
| _ -> printf "other"
But, as is, you're piping the output from Seq.distinct to a match expression and not Seq.length as you intend.

Related

match by value in a discriminated union, in F#

with this union:
type T =
| A
| B
| C
and a T list
I would like to implement something like this pseudo code:
let countOfType (t: Type) (l: T list) =
l
|> List.filter (fun x -> x.GetType() = t)
|> List.length
when I would pass if I want to count the 'A', 'B', etc..
but A.GetType() and B.GetType() return the T type, so this doesn't work.
Is there a way where I could check the type by passing it as a parameter?
The practical case here is that I have a Map that gets updated every few seconds and its values are part of the same DU. I need to be able to see how many of each type, without having to update the code (like a match block) each time an entry gets added.
Addendum:
I simplified the original question too much and realized it after seeing Fyodor's answer.
So I would like to add the additional part:
how could this also be done for cases like these:
type T =
| A of int
| B of string
| C of SomeOtherType
For such enum type T as you specified, you can just use regular comparison:
let countOfType t (l: T list) =
l
|> List.filter (fun x -> x = t)
|> List.length
Usage:
> countOfType A [A; A; B; C; A]
3
> countOfType B [A; A; B; C; A]
1
Try List.choose: ('a -> 'b option) -> 'a list -> 'b list, it filters list based on 'a -> 'b option selector. If selectors evaluates to Some, then value will be included, if selector evaluates to None, then value will be skipped. If you worry about allocations caused by instantiation of Some, then you'll have to implement version that will use ValueOption
let onlyA lis =
lis |> List.choose (function
| (A _) as a -> Some a
| _ -> None)
let onlyB lis =
lis |> List.choose (function
| (B _) as b -> Some b
| _ -> None)
let lis = [
A 1
A 22
A 333
B ""
B "123"
]
lis |> onlyA |> List.length |> printfn "%d"
You can pattern match, and throw away the data, to create a function for the filter.
type T =
| A of int
| B of string
| C of float
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter (fun x ->
match x with
| A _ -> true
| B _ -> false
| C _ -> false
)
|> List.length
But in general i would asume, that you create a predicate function in your modul.
let isA x =
match x with
| A _ -> true
| _ -> false
if you have those functions you can just write
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter isA
|> List.length

How Reflection MakeUnion three level type?

I want to try to reflect all types of combinations,
I am using a recursive function
Working at two level
But it won't work at the third level.
open Microsoft.FSharp.Reflection
let rec getAll<'A> (c : UnionCaseInfo) : obj [] =
match c.GetFields() |> List.ofSeq with
| [ x ] when FSharpType.IsUnion x.PropertyType ->
FSharpType.GetUnionCases(x.PropertyType)
|> Array.map (fun uc ->
FSharpValue.MakeUnion(c, getAll(uc)))
|> Array.ofSeq
| _ ->
[| FSharpValue.MakeUnion(c, Array.empty) |]
type C = | C1 | C2
//type B = | B1 | B2
type B = | B1 of C | B2
type A =
| A1
| A2toB of B
| A3
static member GetAll =
FSharpType.GetUnionCases(typeof<A>)
|> Seq.collect getAll<A>
|> Seq.cast<A>
|> Array.ofSeq
(A2toB (B1 C1)).ToString() |> printfn "%A"
A.GetAll |> Array.map (fun t -> t.ToString() |> printfn "%A")
"A2toB (B1 C1)"
Unhandled Exception: System.Reflection.TargetParameterCountException: Parameter count mismatch.
when only use two levels
type B = | B1 | B2
Correct return
"A1"
"A2toB B1"
"A2toB B2"
"A3"
The reason you're getting the exception is that when you call getAll in the recursive case for B1, the field type is C, and C has two cases, C1 | C2, so you get back an array of two elements. Then, that array is passed to the MakeUnion call for B1, which expects only one element (a single instance of C). The call fails because there's an unexpected extra C passed in the array.
You can make this work for your example case by adding something like Array.take 1 to your recursive call to getAll, but it won't work in the general case. I'm not entirely sure what you're trying to accomplish, so providing a general solution is currently a little tricky. If you can clarify your requirements, we can probably provide a better solution.
Here's a version that works for your specific example (though as I said, this is not a good general solution):
let rec getAll<'A> (c : UnionCaseInfo) : obj [] =
match c.GetFields() |> List.ofSeq with
| [ x ] when FSharpType.IsUnion x.PropertyType ->
FSharpType.GetUnionCases(x.PropertyType)
|> Array.map (fun uc ->
FSharpValue.MakeUnion(c, getAll(uc) |> Array.take 1))
|> Array.ofSeq
| _ ->
[| FSharpValue.MakeUnion(c, Array.empty) |]
Here's the output:
"A1"
"A2toB (B1 C1)"
"A2toB B2"
"A3"
thanks Aaron M. Eshbach for found my recursive error, I fix my code
let rec getAll<'A> (c: UnionCaseInfo): obj [] =
match c.GetFields() |> List.ofSeq with
| [ x ] when FSharpType.IsUnion x.PropertyType ->
FSharpType.GetUnionCases(x.PropertyType)
|> Array.map (fun uc ->
let t = uc.Name
getAll (uc) |> Array.map (fun a ->
FSharpValue.MakeUnion(c, [| a |]))
)
|> Array.concat
|> Array.ofSeq
| _ ->
let t = c.Name
[| FSharpValue.MakeUnion(c, Array.empty) |]
I think your code can be simplified. Let us reduce the level of nesting by one; utilize an array sequence expression for generation; and also, let's recurse on System.Type instead of on the unwieldy UnionCaseInfo.
The type parameter, removed below, could have been used at run-time only for unboxing the outermost union type. The type of the other generated cases is necessarily obj, also demonstrating the somewhat limited utility of dynamically generated union cases.
let rec getCases t = [|
for ucinfo in FSharpType.GetUnionCases t do
match ucinfo.GetFields() with
| [|pinfo|] when FSharpType.IsUnion pinfo.PropertyType ->
for x in getCases pinfo.PropertyType ->
FSharpValue.MakeUnion(ucinfo, [|x|])
| _ -> yield FSharpValue.MakeUnion(ucinfo, [||]) |]
// val getCases : t:System.Type -> obj []
type A = A1 | A2toB of B | A3
and B = B1 of C | B2
and C = C1 | C2
getCases typeof<A>
// val it : obj [] = [|A1; A2toB (B1 C1); A2toB (B1 C2); A2toB B2; A3|]

Match an Array in F#

I want to pattern match on the command line arguments array.
What I want to do is have a case that matches any case where there's at least one parameter or more and put that first parameter in a variable and then have another case that handles when there are no parameters.
match argv with
| [| first |] -> // this only matches when there is one
| [| first, _ |] -> // this only matches when there is two
| [| first, tail |] -> // not working
| argv.[first..] -> // this doesn't compile
| [| first; .. |] -> // this neither
| _ -> // the other cases
You can use truncate:
match args |> Array.truncate 1 with
| [| x |] -> x
| _ -> "No arguments"
If you convert argv to a list using Array.toList, you can then pattern match on it as a list using the cons operator, :::
match argv |> Array.toList with
| x::[] -> printfn "%s" x
| x::xs -> printfn "%s, plus %i more" x (xs |> Seq.length)
| _ -> printfn "nothing"
The closest thing you'll get without converting to a list is:
match argv with
| arr when argv.Length > 0 ->
let first = arr.[0]
printfn "%s" first
| _ -> printfn "none"
If you just want the first item, I prefer Array.tryHead:
match Array.tryHead items with
| Some head -> printfn "%O" head
| None -> printfn "%s" "No items"

Splitting a list by alternating elements

I'm trying to split an F# list into two by taking alternate elements. Here's my attempt:
let split l =
let rec loop l isEven result1 result2 =
match l with
| [] -> result1 result2
| [head::tail] when isEven -> loop tail (not isEven) head::result1 result2
| [head::tail] -> loop tail (not isEven) result1 head::result2
loop l false [] []
That gives me an error:
Program.fs(5,39): error FS0001: Type mismatch. Expecting a
'a
but given a
'b -> 'a list
The resulting type would be infinite when unifying ''a' and ''b -> 'a list'
I don't see how it can be infinite, and I don't understand why it thinks I'm giving it a function from 'b to 'a list. Could somebody tell me where I'm going wrong?
Jack did a good job of explaining what's wrong. Here's an alternate solution that matches two elements at a time. F#'s pattern matching documentation has a lot of great examples.
let split list =
let rec split odd even list =
match list with
| a::b::tail -> split (a::odd) (b::even) tail
| a::tail -> split (a::odd) even tail
| [] -> List.rev odd, List.rev even
split [] [] list
Example output.
printfn "%A" (split [1 .. 10])
System.Console.ReadLine() |> ignore
([1; 3; 5; 7; 9], [2; 4; 6; 8; 10])
Here's a fixed version:
let rec loop l isEven result1 result2 =
match l with
| [] ->
result1, result2
| head :: tail when isEven ->
loop tail (not isEven) (head :: result1) result2
| head :: tail ->
loop tail (not isEven) result1 (head :: result2)
In the first case ([]), I added a comma since the the loop function needs to return the values as a tuple. Without the comma, you're basically treating result1 like a function and applying result2 to it.
The empty list pattern was correct ([]) but in the other cases, you don't use the brackets -- just the cons (::) pattern.
You needed to enclose the head :: result in parenthesis, otherwise F# reads the code as if you wrote this: (loop tail (not isEven) head) :: (result1 result2).
Oh, and if you want the lists you're returning to be in the same order as the original list, you need to use List.rev when you return the lists, like this:
match l with
| [] ->
List.rev result1, List.rev result2
Finally, here's a slightly simplified version of your function -- you don't really need the isEven parameter to make the function work. Instead, you just try to keep the lists the same length:
let rec loop (result1, result2) l =
match l with
| [] ->
List.rev result1, List.rev result2
| hd :: tl ->
if List.length result1 = List.length result2 then
loop (hd :: result1, result2) tl
else
loop (result1, hd :: result2) tl
The simplest solution is not tail recursive but is very comprehensible:
let prepend2 (x, y) (xs, ys) = x::xs, y::ys
let rec split = function
| [] | [_] as xs -> xs, []
| x0::x1::xs -> prepend2 (x0, x1) (split xs)

How to code Fizzbuzz in F#

I am currently learning F# and have tried (an extremely) simple example of FizzBuzz.
This is my initial attempt:
for x in 1..100 do
if x % 3 = 0 && x % 5 = 0 then printfn "FizzBuzz"
elif x % 3 = 0 then printfn "Fizz"
elif x % 5 = 0 then printfn "Buzz"
else printfn "%d" x
What solutions could be more elegant/simple/better (explaining why) using F# to solve this problem?
Note: The FizzBuzz problem is going through the numbers 1 to 100 and every multiple of 3 prints Fizz, every multiple of 5 prints Buzz, every multiple of both 3 AND 5 prints FizzBuzz. Otherwise, simple the number is displayed.
Thanks :)
I think you already have the "best" solution.
If you want to show off more functional/F#-isms, you could do e.g.
[1..100]
|> Seq.map (function
| x when x%5=0 && x%3=0 -> "FizzBuzz"
| x when x%3=0 -> "Fizz"
| x when x%5=0 -> "Buzz"
| x -> string x)
|> Seq.iter (printfn "%s")
and use lists, sequences, map, iter, patterns, and partial application.
[1..100] // I am the list of numbers 1-100.
// F# has immutable singly-linked lists.
// List literals use square brackets.
|> // I am the pipeline operator.
// "x |> f" is just another way to write "f x".
// It is a common idiom to "pipe" data through
// a bunch of transformative functions.
Seq.map // "Seq" means "sequence", in F# such sequences
// are just another name for IEnumerable<T>.
// "map" is a function in the "Seq" module that
// applies a function to every element of a
// sequence, returning a new sequence of results.
(function // The function keyword is one way to
// write a lambda, it means the same
// thing as "fun z -> match z with".
// "fun" starts a lambda.
// "match expr with" starts a pattern
// match, that then has |cases.
| x when x%5=0 && x%3=0
// I'm a pattern. The pattern is "x", which is
// just an identifier pattern that matches any
// value and binds the name (x) to that value.
// The "when" clause is a guard - the pattern
// will only match if the guard predicate is true.
-> "FizzBuzz"
// After each pattern is "-> expr" which is
// the thing evaluated if the pattern matches.
// If this pattern matches, we return that
// string literal "FizzBuzz".
| x when x%3=0 -> "Fizz"
// Patterns are evaluated in order, just like
// if...elif...elif...else, which is why we did
// the 'divisble-by-both' check first.
| x when x%5=0 -> "Buzz"
| x -> string x)
// "string" is a function that converts its argument
// to a string. F# is statically-typed, so all the
// patterns have to evaluate to the same type, so the
// return value of the map call can be e.g. an
// IEnumerable<string> (aka seq<string>).
|> // Another pipeline; pipe the prior sequence into...
Seq.iter // iter applies a function to every element of a
// sequence, but the function should return "unit"
// (like "void"), and iter itself returns unit.
// Whereas sequences are lazy, "iter" will "force"
// the sequence since it needs to apply the function
// to each element only for its effects.
(printfn "%s")
// F# has type-safe printing; printfn "%s" expr
// requires expr to have type string. Usual kind of
// %d for integers, etc. Here we have partially
// applied printfn, it's a function still expecting
// the string, so this is a one-argument function
// that is appropriate to hand to iter. Hurrah!
My example is just a minor improvement over the code posted by 'ssp'. It uses parameterized active patterns (which take the divisor as an argument). Here is a more in-depth explanation:
The following defines an active pattern that we can later use in the match
expression to test if a value i is divisible by a value divisor. When we write:
match 9 with
| DivisibleBy 3 -> ...
...it means that the value '9' will be passed to the following function as i and the value 3 will be passed as divisor. The name (|DivisibleBy|_|) is a special syntax, whith means that we're declaring an active pattern (and the name can appear in the
match on the left side of ->. The |_| bit means that the pattern can fail (our example fails when value is not divisible by divisor)
let (|DivisibleBy|_|) divisor i =
// If the value is divisible, then we return 'Some()' which
// represents that the active pattern succeeds - the '()' notation
// means that we don't return any value from the pattern (if we
// returned for example 'Some(i/divisor)' the use would be:
// match 6 with
// | DivisibleBy 3 res -> .. (res would be asigned value 2)
// None means that pattern failed and that the next clause should
// be tried (by the match expression)
if i % divisor = 0 then Some () else None
Now we can iterate over all the numbers and match them against patterns (our active pattern) using match (or using Seq.iter or some other technique as shown in other answers):
for i in 1..100 do
match i with
// & allows us to run more than one pattern on the argument 'i'
// so this calls 'DivisibleBy 3 i' and 'DivisibleBy 5 i' and it
// succeeds (and runs the body) only if both of them return 'Some()'
| DivisibleBy 3 & DivisibleBy 5 -> printfn "FizzBuzz"
| DivisibleBy 3 -> printfn "Fizz"
| DivisibleBy 5 -> printfn "Buzz"
| _ -> printfn "%d" i
For more information on F# active patterns, here is an MSDN documentation link. I think that if you remove all the comments, the code will be slightly more readable than the original version. It shows some quite useful tricks :-), but in your case, the task is relatively easy...
Yet one solution in F# style (i.e. with Active Patterns usage):
let (|P3|_|) i = if i % 3 = 0 then Some i else None
let (|P5|_|) i = if i % 5 = 0 then Some i else None
let f = function
| P3 _ & P5 _ -> printfn "FizzBuzz"
| P3 _ -> printfn "Fizz"
| P5 _ -> printfn "Buzz"
| x -> printfn "%d" x
Seq.iter f {1..100}
//or
for i in 1..100 do f i
To add one more possible answer - here is another approach without pattern matching. It uses the fact that Fizz + Buzz = FizzBuzz, so you don't actually need to test for all three cases, you only need to see if it is divisible by 3 (then print "Fizz") and also see if it is divisible by 5 (then print "Buzz") and finally, print a new line:
for i in 1..100 do
for divisor, str in [ (3, "Fizz"); (5, "Buzz") ] do
if i % divisor = 0 then printf "%s" str
printfn ""
The nested for loop assignes 3 and "Fizz" to divisor and str in the first iteration and then the second pair of values in the second iteration. The beneift is, you could easily add printing of "Jezz" when the value is divisible by 7 :-) ...in case that extensibility of the solution is a concern!
Here's one more:
let fizzy num =
match num%3, num%5 with
| 0,0 -> "fizzbuzz"
| 0,_ -> "fizz"
| _,0 -> "buzz"
| _,_ -> num.ToString()
[1..100]
|> List.map fizzy
|> List.iter (fun (s:string) -> printfn "%s" s)
I find this to be a bit more readable answer edited was inspired a bit by the others
let FizzBuzz n =
match n%3,n%5 with
| 0,0 -> "FizzBuzz"
| 0,_ -> "Fizz"
| _,0 -> "Buzz"
| _,_ -> string n
[1..100]
|> Seq.map (fun n -> FizzBuzz n)
|> Seq.iter (printfn "%s")
Here is my version:
//initialize array a with values from 1 to 100
let a = Array.init 100 (fun x -> x + 1)
//iterate over array and match *indexes* x
Array.iter (fun x ->
match x with
| _ when x % 15 = 0 -> printfn "FizzBuzz"
| _ when x % 5 = 0 -> printfn "Buzz"
| _ when x % 3 = 0 -> printfn "Fizz"
| _ -> printfn "%d" x
) a
This is my first program in F#.
It's not perfect, but I think someone who starts learning F# (like me :)) can figure out what happens here quite fast.
However I am wondering what is the difference between matching to any _ or to x itself in pattern matching above?
I couldn't find a working solution that didn't include testing for i % 15 = 0. I've always felt that not testing for that is part of this "stupid" assignment. Be aware that this is probably not idiomatic F# since it's my first program in the language.
for n in 1..100 do
let s = seq {
if n % 3 = 0 then yield "Fizz"
if n % 5 = 0 then yield "Buzz" }
if Seq.isEmpty s then printf "%d"n
printfn "%s"(s |> String.concat "")
Here's a version emphasizing a generic tuple list of carbonations:
let carbonations = [(3, "Spizz") ; (5, "Fuzz"); (15, "SpizzFuzz");
(30, "DIZZZZZZZZ"); (18, "WHIIIIII")]
let revCarbonated = carbonations |> List.sort |> List.rev
let carbonRoute someCarbonations findMe =
match(List.tryFind (fun (x,_) -> findMe % x = 0) someCarbonations) with
| Some x -> printfn "%d - %s" findMe (snd x)
| None -> printfn "%d" findMe
let composeCarbonRoute = carbonRoute revCarbonated
[1..100] |> List.iter composeCarbonRoute
I don't like all these repeated strings, here's mine:
open System
let ar = [| "Fizz"; "Buzz"; |]
[1..100] |> List.map (fun i ->
match i % 3 = 0, i % 5 = 0 with
| true, false -> ar.[0]
| false, true -> ar.[1]
| true, true -> ar |> String.Concat
| _ -> string i
|> printf "%s\n"
)
|> ignore
Here is an attempt that factors out the modulo checks
let DivisibleBy x y = y % x = 0
[ 1 .. 100 ]
|> List.map (function
| x when DivisibleBy (3 * 5) x -> "fizzbuzz"
| x when DivisibleBy 3 x -> "fizz"
| x when DivisibleBy 5 x -> "buzz"
| x -> string x)
|> List.iter (fun x -> printfn "%s" x)
Here is how I refined it

Resources