Project new values from existing value - f#

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);;

Related

F# Change element in list and return full new list

I have a list of type (string * (int * int)) list. I want to be able to search through the list, finding the right element by it's string identifier, do a calculation on one of the ints, and then return the full, modified list.
Example:
Given a list
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
I'm trying to make a function which gets one of the elements and subtracts number from one of the ints in the tuple.
get ("a2",10) st
//Expected result: st' = [("a1",(100,10)); ("a2",(40,20)); ("a3",(25,40))]
I feel I'm almost there, but am a little stuck with the following function:
let rec get (a,k) st =
match st with
| (a',(n',p'))::rest when a'=a && k<=n' -> (n'-k,p')::rest
| (a',(n',p'))::rest -> (n',p')::get (a,k) rest
| _ -> failwith "Illegal input"
This returns [("a2",(40,20)); ("a3",(25,40))] and is thus missing the first a1 element. Any hints?
Lists are immutable, so if you want to "change one element" you are really creating a new list with one element transformed. The easiest way to do a transformation like this is to use List.map function. I would write something like:
let updateElement key f st =
st |> List.map (fun (k, v) -> if k = key then k, f v else k, v)
updateElement is a helper that takes a key, update function and an input. It returns list where the element with the given key has been transformed using the given function. For example, to increment the first number associated with a2, you can write:
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
st |> updateElement "a2" (fun (a, b) -> a + 10, b)
I was looking for a function which would update an element in a list based on the element's data. I couldn't find one in F#5, so wrote one using Tomas' solution:
let updateAt (elemFindFunc: 'a -> bool) (newElem: 'a) (source: 'a list) : 'a list =
source
|> List.map
(fun elem ->
let foundElem = elemFindFunc elem
if foundElem then newElem else elem)
elemFindFunc is the function which consumes an element and returns true if this is the element we want to replace. If this function returns true for multiple elements, then those will be replaced by newElem. Also, if elemFindFunc evaluates to false for all elements, the list will be unaltered.
newElem is the new value you want to replace with. newElem could be replaced by a function like valueFunc: 'a -> 'a if you want to process the element before inserting it.

Function argument is null, even though a non-null argument is passed

F# newbie here, and sorry for the bad title, I'm not sure how else to describe it.
Very strange problem I'm having. Here's the relevant code snippet:
let calcRelTime (item :(string * string * string)) =
tSnd item
|>DateTime.Parse
|> fun x -> DateTime.Now - x
|> fun y -> (floor y.TotalMinutes).ToString()
|>makeTriple (tFst item) (tTrd item) //makeTriple switches y & z. How do I avoid having to do that?
let rec getRelativeTime f (l :(string * string * string) list) =
match l with
| [] -> f
| x :: xs -> getRelativeTime (List.append [calcRelTime x] f) xs
I step through it with Visual Studio and it clearly shows that x in getRelativeTime is a 3-tuple with a well-formed datetime string. But when I step to calcRelTime item is null. Everything ends up returning a 3-tuple that has the original datetime string, instead of one with the total minutes past. There's no other errors anywhere, until the that datetime string hits a function that expects it to be an integer string.
Any help would be appreciated! (along with any other F# style tips/suggestions for these functions).
item is null, because it hasn't been constructed yet out of its parts. The F# compiler compiles tupled parameters as separate actual (IL-level) parameters rather than one parameter of type Tuple<...>. If you look at your compiled code in ILSpy, you will see this signature (using C# syntax):
public static Tuple<string, string, string> calcRelTime(string item_0, string item_1, string item_2)
This is done for several reasons, including interoperability with other CLR languages as well as efficiency.
To be sure, the tuple itself is then constructed from these arguments (unless you have optimization turned on), but not right away. If you make one step (hit F11), item will obtain a proper non-null value.
You can also see these compiler-generated parameters if you go to Debug -> Windows -> Locals in Visual Studio.
As for why it's returning the original list instead of modified one, I can't really say: on my setup, everything works as expected:
> getRelativeTime [] [("x","05/01/2015","y")]
val it : (string * string * string) list = [("x", "y", "17305")]
Perhaps if you share your test code, I would be able to tell more.
And finally, what you're doing can be done a lot simpler: you don't need to write a recursive loop yourself, it's already done for you in the many functions in the List module, and you don't need to accept a tuple and then deconstruct it using tFst, tSnd, and tTrd, the compiler can do it for you:
let getRelativeTime lst =
let calcRelTime (x, time, y) =
let parsed = DateTime.Parse time
let since = DateTime.Now - parsed
let asStr = (floor since.TotalMinutes).ToString()
(x, asStr, y)
List.map calRelTime lst
let getRelativeTime' list =
let calc (a, b, c) = (a, c, (floor (DateTime.Now - (DateTime.Parse b)).TotalMinutes).ToString())
list |> List.map calc
Signature of the function is val getRelativeTime : list:('a * string * 'b) list -> ('a * 'b * string) list
You can deconstruct item in the function declaration to (a, b, c), then you don't have to use the functions tFst, tSnd and tTrd.
The List module has a function map that applies a function to each element in a list and returns a new list with the mapped values.

F#: Updating a single tuple in a list of tuples

I have a list of tuples like so:
let scorecard = [ for i in 0 .. 39 -> i,0 ]
I want to identify the nth tuple in it. I was thinking about it in this way:
let foundTuple = scorecard |> Seq.find(fun (x,y) -> x = 10)
I then want to create a new tuple based on the found one:
let newTuple = (fst foundTuple, snd foundTuple + 1)
And have a new list with that updated value
Does anyone have some code that matches this pattern? I think I have to split the list into 2 sublists: 1 list has 1 element (the tuple I want to replace) and the other list has the remaining elements. I then create a new list with the replacing tuple and the list of unchanged tuples...
You can use List.mapi which creates a new list using a specified projection function - but it also calls the projection function with the current index and so you can decide what to do based on this index.
For example, to increment second element of a list of integers, you can do:
let oldList = [0;0;0;0]
let newList = oldList |> List.mapi (fun index v -> if index = 1 then v + 1 else v)
Depending on the problem, it might make sense to use the Map type instead of list - map represents a mapping from keys to values and does not need to copy the entire contents when you change just a single value. So, for example:
// Map keys from 0 to 3 to values 0
let m = Map.ofList [0,0;1,0;2,0;3,0]
// Set the value at index 1 to 10 and get a new map
Map.add 1 10 m
I went back and thought about the problem and decided to use an array, which is mutable.
let scorecard = [| for i in 0 .. 39 -> i,0 |]
Since tuples are not mutable, I need to create a new tuple based on the existing one and overwrite it in the array:
let targetTuple = scorecard.[3]
let newTuple = (fst targetTuple, snd targetTuple + 1)
scorecard.[3] <- newTuple
I am using the "<-" which is a code smell in F#. I wonder if there a comparable purely functional equivalent?

error with f# generic follow Expert Fsharp book example

I'm reading Expert F# book and I found this code
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
and the example use:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
first for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang..specially compared to clojure. But the problem is not this...I'm having problems with the Dictionary definition
when I type this:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
I get this:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
is It ok?...
thanks so much
improve question:
Ok I've been reading about value restriction and I found this helpfull information
In particular, only function definitions and simple immutable data
expressions are automatically generalized
...ok..this explains why
let dict = new Dictionary<'key,ResizeArray<'T>>();;
doesn't work...and show 4 different techniques, although in my opinion they only resolve the error but aren't solutions for use generic code:
Technique 1: Constrain Values to Be Nongeneric
let empties : int list [] = Array.create 100 []
Technique 3: Add Dummy Arguments to Generic Functions When Necessary
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
Technique 4: Add Explicit Type Arguments When Necessary (similar to tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- and the only one than let me use real generic code ------
Technique 2: Ensure Generic Functions Have Explicit Arguments
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
Ok, in 3 of 4 techniques I need resolve the generic code before can work with this...now...returning to book example...when the compile knows the value for 'key and 'T
let dict = new Dictionary<'key,ResizeArray<'T>>()
in the scope the code is very generic for let key be any type, the same happen with 'T
and the biggest dummy question is :
when I enclose the code in a function (technique 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
for me (admittedly I'm a little dummy with static type languages) this is not real generic because it can't infer the type when I use it, I need define the type and then pass values (not define its type based in the passed values) exist other way define type without be so explicit..
thanks so much..really appreciate any help
This line
let dict = new Dictionary<'key,ResizeArray<'T>>();;
fails because when you type the ;; the compiler doesn't know what 'key and 'T are. As the error message states you need to add a type annotation, or allow the compiler to infer the type by using it later or make it a function
Examples
Type annotation change
let dict = new Dictionary<int,ResizeArray<int>>();;
Using types later
let dict = new Dictionary<'key,ResizeArray<'T>>()
dict.[1] <- 2
using a function
let dict() = new Dictionary<'key,ResizeArray<'T>>();;
This actually doesn't cause an issue when it's defined all together. That is, select the entire block that you posted and send it to FSI in one go. I get this:
val divideIntoEquivalenceClasses :
('T -> 'key) -> seq<'T> -> seq<'key * seq<'T>> when 'key : equality
However, if you type these individually into FSI then as John Palmer says there is not enough information in that isolated line for the interpreter to determine the type constraints. John's suggestions will work, but the original code is doing it correctly - defining the variable and using it in the same scope so that the types can be inferred.
for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang.
I agree completely – it's slightly tangential to your direct question, but I think a more idiomatic (functional) approach would be:
let divideIntoEquivalenceClasses keyf seq =
(System.Collections.Generic.Dictionary(), seq)
||> Seq.fold (fun dict v ->
let key = keyf v
match dict.TryGetValue key with
| false, _ -> dict.Add (key, ResizeArray(Seq.singleton v))
| _, prev -> prev.Add v
dict)
|> Seq.map (function KeyValue (k, v) -> k, Seq.readonly v)
This allows sufficient type inference to obviate the need for your question in the first place.
The workarounds proposed by the other answers are all good. Just to clarify based on your latest updates, let's consider two blocks of code:
let empties = Array.create 100 []
as opposed to:
let empties = Array.create 100 []
empties.[0] <- [1]
In the second case, the compiler can infer that empties : int list [], because we are inserting an int list into the array in the second line, which constrains the element type.
It sounds like you'd like the compiler to infer a generic value empties : 'a list [] in the first case, but this would be unsound. Consider what would happen if the compiler did that and we then entered the following two lines in another batch:
empties.[0] <- [1] // treat 'a list [] as int list []
List.iter (printfn "%s") empties.[0] // treat 'a list [] as string list []
Each of these lines unifies the generic type parameter 'a with a different concrete type (int and string). Either of these unifications is fine in isolation, but they are incompatible with each other and would result in treating the int value 1 inserted by the first line as a string when the second line is executed, which is clearly a violation of type safety.
Contrast this with an empty list, which really is generic:
let empty = []
Then in this case, the compiler does infer empty : 'a list, because it's safe to treat empty as a list of different types in different locations in your code without ever impacting type safety:
let l1 : int list = empty
let l2 : string list = empty
let l3 = 'a' :: empty
In the case where you make empties the return value of a generic function:
let empties() = Array.create 100 []
it is again safe to infer a generic type, since if we try our problematic scenario from before:
empties().[0] <- [1]
List.iter (printfn "%s") (empties().[0])
we are creating a new array on each line, so the types can be different without breaking the type system.
Hopefully this helps explain the reasons behind the limitation a bit more.

Can existing types be extended to work with Seq.sum, etc?

Been working with a lot of TimeSpans recently, and have a need to get sums & averages.
However, TimeSpan defines neither operator get_Zero nor DivideByInt, so Seq.sum and Seq.average can't be used directly with this type. The following fails to compile:
open System
type System.TimeSpan
with
static member Zero with get() = TimeSpan()
static member (/) (n:DateTime, d:int) = DateTime( n.Ticks / (int64) d )
let ts = [ TimeSpan(10L); TimeSpan(99L) ]
let sum = ts |> Seq.sum
let avg = ts |> Seq.average
Error: The type 'TimeSpan' does not support any operators named 'get_Zero'
Error: The type 'TimeSpan' does not support any operators named 'DivideByInt'
Warning: Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead.
Is there some F# magic that can define these operators on an existing type?
I know the following will work (and should be more efficient to boot), but I'm still curious about the above so I can add it to my toolbox for use with other types.
let sum = TimeSpan( ts |> Seq.sumBy (fun t -> t.Ticks) )
let avg = TimeSpan( let len = ts |> Seq.length in sum.Ticks / int64 len )
As far as I know, static member constraints (that are used by functions like Seq.sum) are not able to discover members that are added by type extensions (essentially, extension methods), so I don't think there is a direct way of doing this.
The best option I can think of is to creat a simple wrapper around the System.TimeSpan struct. Then you can define all the required members. The code would look like this:
[<Struct>]
type TimeSpan(ts:System.TimeSpan) =
member x.TimeSpan = ts
new(ticks:int64) = TimeSpan(System.TimeSpan(ticks))
static member Zero = TimeSpan(System.TimeSpan.Zero)
static member (+) (a:TimeSpan, b:TimeSpan) =
TimeSpan(a.TimeSpan + b.TimeSpan)
static member DivideByInt (n:TimeSpan, d:int) =
TimeSpan(n.TimeSpan.Ticks / (int64 d))
let ts = [ TimeSpan(10L); TimeSpan(99L) ]
let sum = ts |> Seq.sum
let avg = ts |> Seq.average
I called the type TimeSpan, so it hides the standard System.TimeSpan type. However, you still need to write ts.TimeSpan when you need to access the underlying system type, so this isn't as nice as it could be.
Mhh the following is rather ugly, but it works. Does it help? I define a wrapper for TimeSpan that can implicitly be converted back to a TimeSpan.
type MyTimeSpan(ts : TimeSpan) =
member t.op_Implicit : TimeSpan = ts
static member (+) (t1 : MyTimeSpan, t2 : MyTimeSpan) =
new MyTimeSpan(TimeSpan.FromTicks(t1.op_Implicit.Ticks + t2.op_Implicit.Ticks))
static member Zero = new MyTimeSpan(TimeSpan.Zero)
static member DivideByInt (t : MyTimeSpan, i : int) =
new MyTimeSpan(TimeSpan.FromTicks(int64 (float t.op_Implicit.Ticks / float i)))
let toMyTS ts = new MyTimeSpan(ts)
let l = [TimeSpan.FromSeconds(3.); TimeSpan.FromSeconds(4.)]
|> List.map toMyTS
|> List.average

Resources