Currently I have a function to return the first elements of each list (floats), within a list to a separate list.
let firstElements list =
match list with
| head::_ -> head
| [] -> 0.00
My question is, how do I expand this to return elements at the same index into different lists while I don't know how long this list is? For example
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
If I did not know the length of this list, what is the most efficient and safest way to get
[[1;4;7];[2;5;8];[3;6;9]]
List.transpose has been added recently to FSharp.Core
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
let res = biglist |> List.transpose
//val res : int list list = [[1; 4; 7]; [2; 5; 8]; [3; 6; 9]]
You can use the recent added List.transpose function. But it is always good to be good enough to create such functions yourself. If you want to solve the problem yourself, think of a general algorithm to solve your problem. One would be.
From the first element of each list you create a new list
You drop the first element of each list
If you end with empty lists you end, otherwise repeat at step 1)
This could be the first attempt to solve the Problem. Function names are made up, at this point.
let transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else ...
The else branch looks like following. First we want to pick the first element of every element. We imagine a function pickFirsts that do this task. So we could write pickFirsts lst. The result is a list that itself is the first element of a new list.
The new list is the result of the remaining list. First we imagine again a function that drops the first element of every sub-list dropFirsts lst. On that list we need to repeat step 1). We do that by a recursive call to transpose.
Overall we get:
let rec transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else (pickFirsts lst) :: (transpose (dropFirsts lst))
At this point we can think of the default value. transpose needs to return a value in the case it ends up with an empty list of empty lists. As we use the result of transpose to add an element to it. The results of it must be a list. And the best default value is an empty list. So we end up with.
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
Next we need to implement the remaining functions allEmpty, pickFirsts and dropFirsts.
pickFirst is easy. We need to iterate over each element, and must return the first value. We get the first value of a list by List.head, and iterating over it and turning every element into a new list is what List.map does.
let pickFirsts lst = List.map List.head lst
dropFirsts need to iterate ver each element, and just remove the first element, or in other words keeps the remaining/tail of a list.
let dropFirsts lst = List.map List.tail lst
The remaining allEmpty is a predicate that either return true/false if we have an empty list of lists or not. With a return value of bool, we need another function that allows to return another type is a list. This is usually the reason to use List.fold. An implementation could look like this:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
It starts with true as the default value. As long it finds empty lists it returns the default value unchanged. As soon there is one element found, in any list, it will return false (Not Empty) as the new default value.
The whole code:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
let pickFirsts lst = List.map List.head lst
let dropFirsts lst = List.map List.tail lst
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
transpose [[1;2;3];[4;5;6];[7;8;9]]
Another approach would be to turn it into a 2 dimensional mutable array. Also do length checkings. Do the transformation and return the mutable array again as an immutable list.
Related
How do I append a value to the end of a list?
let rec add lst value =
match lst with
| [] -> [value]
This currently only appends an empty list with the value x. How would I add a value to the end of a list that has elements in already in it?
For simple recursive version use
let rec add lst value =
match lst with
| [] -> [ value ]
| h :: t -> h :: add t value
Note that this implementation is not tail recursive.
But in pratice use the built in append operator
let add lst value = lst # [ value ]
Or the standard function List.append which has the arguments in an other order.
let add lst value = List.append [ value ] lst
Also worth knowingis that append is an expensive function on a singly linked immutable list which create a new copy of the entire list.
Is there anyway to contruct a list in reverse order without having to reverse it
Here is an example, I read all lines from stdin
#!/usr/bin/env dotnet fsi
open System
let rec readLines1 () =
let rec helper acc =
match Console.ReadLine() with
| null -> acc
| line ->
helper (line :: acc)
helper [] |> List.rev
readLines1 () |> List.iter (printfn "%s")
Before return from readLines1 I have to List.rev it so that is in right order. Since the result is a slightly linked list it will have to read all trough it and create the reversed version. Is there any way of creating the list in right order?
You can use a sequence instead of accumulating the lines in a list:
open System
let readLines1 () =
let rec helper () =
seq {
match Console.ReadLine() with
| null -> ()
| line ->
yield line
yield! helper ()
}
helper () |> Seq.toList
readLines1 () |> List.iter (printfn "%s")
You cannot create list in reverse order, because that would require mutation. If you read inputs one by one, and want to turn them into a list immediately, the only thing you can do is to create new list, linking to the previous one.
In practice, reversing the list is perfectly fine and that's probably the best way of solving this.
Out of curiosity, you could try defininig a mutable list that has the same structure as immutable F# list:
open System
type MutableList<'T> =
{ mutable List : MutableListBody<'T> }
and MutableListBody<'T> =
| Empty
| Cons of 'T * MutableList<'T>
Now you can implement your function by mutating the list:
let rec readLines () =
let res = { List = Empty }
let rec helper acc =
match Console.ReadLine() with
| null -> res
| line ->
let next = { List = Empty }
acc.List <- Cons(line, next)
helper next
helper res
This may be educational, but it's not very useful and, if you really wanted mutation in F#, you should probably use ResizeArray.
Yet another trick is to work with functions that take the tail of the list:
let rec readLines () =
let rec helper acc =
match Console.ReadLine() with
| null -> acc []
| line -> helper (fun tail -> acc (line :: tail))
helper id
In the line case, this returns a function that takes tail adds line before the tail and then calls whatever function was constructed before to add more things to the front.
This actually creates the list in the right order, but it's probably less efficient than creating a list and reversing it. It may look nice, but you are allocating a new function for each iteration, which is not better than allocating an extra copy of the list. (But it is a nice trick, nevertheless!)
Alternative solution without implementing recursive functions
let lines =
Seq.initInfinite (fun _ -> Console.ReadLine())
|> Seq.takeWhile (not << isNull)
|> Seq.toList
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.
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?
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.