Accessing tuple item from discriminated union - f#

I have type called type x and it has following members in the form of discriminated union
type Info= Empty | Value of int | Pair of (int * int)
I have a function which takes two arguments and filter the list according to comparisons made by n. I cannot figure out the last part. How can I compare each value of Pair with my n value in that function?
let filterInfo (n:int) (xs:Info list) = xs |> List.filter (fun (x) -> x <> Empty && x > Value n && // )

You can create a function that compares a single Info object by using pattern matching. Something like this should suffice:
let compareInfo (n:int) (info:Info) =
match info with
| Empty -> false
| Value x -> n > x
| Pair (a, b) -> ...
You can call it by curring n from your filter call:
let filterInfo (n:int) (xs:Info list) = xs |> List.filter (compareInfo n)

I ended up adding a read-only property that pattern-matches on this:
type Thing =
| Sphere of Sphere * Surface
| Plane of Plane * Surface
member this.surface =
match this with
| Sphere(_, surface) -> surface
| Plane(_, surface) -> surface

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

Tail Recursive map f#

I want to write a tail recursive function to multiply all the values in a list by 2 in F#. I know there is a bunch of ways to do this but i want to know if this is even a viable method. This is purely for educational purposes. I realize that there is a built in function to do this for me.
let multiply m =
let rec innerfunct ax = function
| [] -> printfn "%A" m
| (car::cdr) -> (car <- car*2 innerfunct cdr);
innerfunct m;;
let mutable a = 1::3::4::[]
multiply a
I get two errors with this though i doubt they are the only problems.
This value is not mutable on my second matching condition
and
This expression is a function value, i.e. is missing arguments. Its type is 'a list -> unit. for when i call length a.
I am fairly new to F# and realize im probably not calling the function properly but i cant figure out why. This is mostly a learning experience for me so the explanation is more important than just fixing the code. The syntax is clearly off, but can i map *2 to a list just by doing the equivalent of
car = car*2 and then calling the inner function on the cdr of the list.
There are a number of issues that I can't easily explain without showing intermediate code, so I'll try to walk through a commented refactoring:
First, we'll go down the mutable path:
As F# lists are immutable and so are primitive ints, we need a way to mutate that thing inside the list:
let mutable a = [ref 1; ref 3; ref 4]
Getting rid of the superfluous ax and arranging the cases a bit, we can make use of these reference cells:
let multiply m =
let rec innerfunct = function
| [] -> printfn "%A" m
| car :: cdr ->
car := !car*2
innerfunct cdr
innerfunct m
We see, that multiply only calls its inner function, so we end up with the first solution:
let rec multiply m =
match m with
| [] -> printfn "%A" m
| car :: cdr ->
car := !car*2
multiply cdr
This is really only for it's own purpose. If you want mutability, use arrays and traditional for-loops.
Then, we go up the immutable path:
As we learnt in the mutable world, the first error is due to car not being mutable. It is just a primitive int out of an immutable list. Living in an immutable world means we can only create something new out of our input. What we want is to construct a new list, having car*2 as head and then the result of the recursive call to innerfunct. As usual, all branches of a function need to return some thing of the same type:
let multiply m =
let rec innerfunct = function
| [] ->
printfn "%A" m
[]
| car :: cdr ->
car*2 :: innerfunct cdr
innerfunct m
Knowing m is immutable, we can get rid of the printfn. If needed, we can put it outside of the function, anywhere we have access to the list. It will always print the same.
We finish by also making the reference to the list immutable and obtain a second (intermediate) solution:
let multiply m =
let rec innerfunct = function
| [] -> []
| car :: cdr -> car*2 :: innerfunct cdr
innerfunct m
let a = [1; 3; 4]
printfn "%A" a
let multiplied = multiply a
printfn "%A" multiplied
It might be nice to also multiply by different values (the function is called multiply after all and not double). Also, now that innerfunct is so small, we can make the names match the small scope (the smaller the scope, the shorter the names):
let multiply m xs =
let rec inner = function
| [] -> []
| x :: tail -> x*m :: inner tail
inner xs
Note that I put the factor first and the list last. This is similar to other List functions and allows to create pre-customized functions by using partial application:
let double = multiply 2
let doubled = double a
All that's left now is to make multiply tail-recursive:
let multiply m xs =
let rec inner acc = function
| [] -> acc
| x :: tail -> inner (x*m :: acc) tail
inner [] xs |> List.rev
So we end up having (for educational purposes) a hard-coded version of let multiply' m = List.map ((*) m)
F# is a 'single-pass' compiler, so you can expect any compilation error to have a cascading effect beneath the error. When you have a compilation error, focus on that single error. While you may have more errors in your code (you do), it may also be that subsequent errors are only consequences of the first error.
As the compiler says, car isn't mutable, so you can assign a value to it.
In Functional Programming, a map can easily be implemented as a recursive function:
// ('a -> 'b) -> 'a list -> 'b list
let rec map f = function
| [] -> []
| h::t -> f h :: map f t
This version, however, isn't tail-recursive, since it recursively calls map before it cons the head onto the tail.
You can normally refactor to a tail-recursive implementation by introducing an 'inner' implementation function that uses an accumulator for the result. Here's one way to do that:
// ('a -> 'b) -> 'a list -> 'b list
let map' f xs =
let rec mapImp f acc = function
| [] -> acc
| h::t -> mapImp f (acc # [f h]) t
mapImp f [] xs
Here, mapImp is the last operation to be invoked in the h::t case.
This implementation is a bit inefficient because it concatenates two lists (acc # [f h]) in each iteration. Depending on the size of the lists to map, it may be more efficient to cons the accumulator and then do a single reverse at the end:
// ('a -> 'b) -> 'a list -> 'b list
let map'' f xs =
let rec mapImp f acc = function
| [] -> acc
| h::t -> mapImp f (f h :: acc) t
mapImp f [] xs |> List.rev
In any case, however, the only reason to do all of this is for the exercise, because this function is already built-in.
In all cases, you can use map functions to multiply all elements in a list by two:
> let mdouble = List.map ((*) 2);;
val mdouble : (int list -> int list)
> mdouble [1..10];;
val it : int list = [2; 4; 6; 8; 10; 12; 14; 16; 18; 20]
Normally, though, I wouldn't even care to define such function explicitly. Instead, you use it inline:
> List.map ((*) 2) [1..10];;
val it : int list = [2; 4; 6; 8; 10; 12; 14; 16; 18; 20]
You can use all the above map function in the same way.
Symbols that you are creating in a match statement are not mutable, so when you are matching with (car::cdr) you cannot change their values.
Standard functional way would be to produce a new list with the computed values. For that you can write something like this:
let multiplyBy2 = List.map (fun x -> x * 2)
multiplyBy2 [1;2;3;4;5]
This is not tail recursive by itself (but List.map is).
If you really want to change values of the list, you could use an array instead. Then your function will not produce any new objects, just iterate through the array:
let multiplyArrayBy2 arr =
arr
|> Array.iteri (fun index value -> arr.[index] <- value * 2)
let someArray = [| 1; 2; 3; 4; 5 |]
multiplyArrayBy2 someArray

f# how to filter mixed data type for a specific type

I m trying to filter a mixed data type for a specific type, say float (ideally this would be dynamic though)
here my example:
let testobj = [8.0 , 1.0, "bla" ; 8.0 , 1.0, "bla"]
let testfun data = data |> List.filter (fun a ->
match a.GetType() with
| float -> a
| _ -> 0.0)
now this should return [8.0 , 1.0, 0.0 ; 8.0 , 1.0, 0.0] for testobj but I m gettting an error that the function is of type bool
This isn't what you want to do.
Seriously.
F# wants lists to be homogeneous and your list is not homogeneous. float and string don't share a common base class so you're not going to get a list from it.
What F# wants you to do is to use a discriminated union for this. So if you have this type:
type Composite =
| Num of float
| Str of string
you can define your list like this:
let data = [ Num(8.0); Num(1.0); Str("bla"); Num(8.0); Num(1.0); Str("bla") ]
and from there you can pattern match on the types and your function looks like this:
let testfun d = d |> List.map (fun a ->
match a with
| Num x -> a
| _ -> Num(0.0) )
data|> testfun |> printfn "%A"
And the output will be:
[Num 8.0; Num 1.0; Num 0.0; Num 8.0 ; Num 1.0 ; Num 0.0;]
If you want floats in the end and not Composites, do this:
let testfun1 d = d |> List.map (fun a ->
match a with
| Num x -> x
| _ -> 0.0 )
which sheds the composite type. And everything (and I mean everything) in that code is type strong and type-safe.
From a real-world maintenance point of view, I would eschew the _ case in the matches and instead use all my types, reasoning that if I extend Composite to include another type I would want the compiler to scream at me and look at each function that uses it rather than silently assuming that 0.0 or Num(0.0) is really what I wanted.
For example, if I added integers to that type, this would do exactly the wrong thing if I wanted to sum the contents of a list of composites.
Given that you're stuck/hell-bent on a weakly-typed data set, then you want something like this:
let testfun2 d = d |> Array.map (fun (a:Object) ->
match a with
| :? float as x -> x
| _ -> 0.0
)
let data:Object[] = [|8.0; 1.0; "bla"; 8.0; 1.0; "bla"|]
data |> testfun2 |> printfn "%A"
which will print what you expect. Note that I'm using proper Array syntax and not list syntax.
However this is feeling really wonky for F#. See how I have to adorn a and d with types? In my previous code, the language can figure it all out. If I don't adorn either, I get compiler errors because we're really going against the grain of the type system.
If I were you, I would be inclined to do something like this first:
let recast d = d |> Array.map (fun (a:Object) ->
match a with
| :? float as x -> Num x
| :? string as x -> Str x
| _ -> raise (ArgumentException("that was unexpected: " + a.GetType().Name))
)
which turns this into an Array of Composite which is now type strong. If you tack on |> Array.toList after the Array.map, you get a list (if you want that).

i think i got infinite loop for this BST

this code i got is from Alexander Battisti about how to make a tree from a list of data:
let data = [4;3;8;7;10;1;9;6;5;0;2]
type Tree<'a> =
| Node of Tree<'a> * 'a * Tree<'a>
| Leaf
let rec insert tree element =
match element,tree with
| x,Leaf -> Node(Leaf,x,Leaf)
| x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
| x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
| _ -> Leaf
let makeTree = List.fold insert Leaf data
then i want to implement this code to my binary search tree code
let rec BinarySearch tree element =
match element,tree with
| x,Leaf -> BinarySearch (Node(Leaf,x,Leaf)) x
| x,Node(l,y,r) when x<=y ->
BinarySearch l y
| x,Node(l,y,r) when x>y ->
BinarySearch r y
| x,Node(l,y,r) when x=y ->
true
| _ -> false
then i use my search code like this:
> BinarySearch makeTree 5;;
and the result is none because it's like i got an infinite looping
can someone help me? if my code is wrong, please help me to correct it, thank you
The solution by Yin is how I would write it too.
Anyway, here is a solution that is closer to your version and (hopefully) explains what went wrong:
let rec BinarySearch tree element =
match element,tree with
| x, Leaf ->
// You originally called 'BinarySearch' here, but that's wrong - if we reach
// the leaf of the tree (on the path from root to leaf) then we know that the
// element is not in the tree so we return false
false
| x, Node(l,y,r) when x<y ->// This needs to be 'x<y', otherwise the clause would be
// matched when 'x=y' and we wouldn't find the element!
BinarySearch l element // Your recursive call was 'BinarySearch l y' but
// that's wrong - you want to search for 'element'
| x, Node(l,y,r) when x>y ->
BinarySearch r element
| x,Node(l,y,r) -> // You can simplify the code by omitting the 'when'
true // clause (because this will only be reached when
// x=y. Then you can omit the last (unreachable) case
let rec BinarySearch tree element =
match tree with
| Leaf -> false
| Node(l, v, r) ->
if v = element then
true
elif v < element then
BinarySearch r element
else
BinarySearch l element
BinarySearch makeTree 5

Avoiding code duplication in F#

I have two snippets of code that tries to convert a float list to a Vector3 or Vector2 list. The idea is to take 2/3 elements at a time from the list and combine them as a vector. The end result is a sequence of vectors.
let rec vec3Seq floatList =
seq {
match floatList with
| x::y::z::tail -> yield Vector3(x,y,z)
yield! vec3Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 3?"
}
let rec vec2Seq floatList =
seq {
match floatList with
| x::y::tail -> yield Vector2(x,y)
yield! vec2Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 2?"
}
The code looks very similiar and yet there seems to be no way to extract a common portion. Any ideas?
Here's one approach. I'm not sure how much simpler this really is, but it does abstract some of the repeated logic out.
let rec mkSeq (|P|_|) x =
seq {
match x with
| P(p,tail) ->
yield p
yield! mkSeq (|P|_|) tail
| [] -> ()
| _ -> failwith "List length mismatch" }
let vec3Seq =
mkSeq (function
| x::y::z::tail -> Some(Vector3(x,y,z), tail)
| _ -> None)
As Rex commented, if you want this only for two cases, then you probably won't have any problem if you leave the code as it is. However, if you want to extract a common pattern, then you can write a function that splits a list into sub-list of a specified length (2 or 3 or any other number). Once you do that, you'll only use map to turn each list of the specified length into Vector.
The function for splitting list isn't available in the F# library (as far as I can tell), so you'll have to implement it yourself. It can be done roughly like this:
let divideList n list =
// 'acc' - accumulates the resulting sub-lists (reversed order)
// 'tmp' - stores values of the current sub-list (reversed order)
// 'c' - the length of 'tmp' so far
// 'list' - the remaining elements to process
let rec divideListAux acc tmp c list =
match list with
| x::xs when c = n - 1 ->
// we're adding last element to 'tmp',
// so we reverse it and add it to accumulator
divideListAux ((List.rev (x::tmp))::acc) [] 0 xs
| x::xs ->
// add one more value to 'tmp'
divideListAux acc (x::tmp) (c+1) xs
| [] when c = 0 -> List.rev acc // no more elements and empty 'tmp'
| _ -> failwithf "not multiple of %d" n // non-empty 'tmp'
divideListAux [] [] 0 list
Now, you can use this function to implement your two conversions like this:
seq { for [x; y] in floatList |> divideList 2 -> Vector2(x,y) }
seq { for [x; y; z] in floatList |> divideList 3 -> Vector3(x,y,z) }
This will give a warning, because we're using an incomplete pattern that expects that the returned lists will be of length 2 or 3 respectively, but that's correct expectation, so the code will work fine. I'm also using a brief version of sequence expression the -> does the same thing as do yield, but it can be used only in simple cases like this one.
This is simular to kvb's solution but doesn't use a partial active pattern.
let rec listToSeq convert (list:list<_>) =
seq {
if not(List.isEmpty list) then
let list, vec = convert list
yield vec
yield! listToSeq convert list
}
let vec2Seq = listToSeq (function
| x::y::tail -> tail, Vector2(x,y)
| _ -> failwith "float array not multiple of 2?")
let vec3Seq = listToSeq (function
| x::y::z::tail -> tail, Vector3(x,y,z)
| _ -> failwith "float array not multiple of 3?")
Honestly, what you have is pretty much as good as it can get, although you might be able to make a little more compact using this:
// take 3 [1 .. 5] returns ([1; 2; 3], [4; 5])
let rec take count l =
match count, l with
| 0, xs -> [], xs
| n, x::xs -> let res, xs' = take (count - 1) xs in x::res, xs'
| n, [] -> failwith "Index out of range"
// split 3 [1 .. 6] returns [[1;2;3]; [4;5;6]]
let rec split count l =
seq { match take count l with
| xs, ys -> yield xs; if ys <> [] then yield! split count ys }
let vec3Seq l = split 3 l |> Seq.map (fun [x;y;z] -> Vector3(x, y, z))
let vec2Seq l = split 2 l |> Seq.map (fun [x;y] -> Vector2(x, y))
Now the process of breaking up your lists is moved into its own generic "take" and "split" functions, its much easier to map it to your desired type.

Resources