i am encountering this problem in F#
[not C# where there is already a similar post with a similar answer]
I understand its not possible to modify a Dictionary while enumerating it in a for loop
how should i go around that ?
let edgelist1 = [(1,2,3.0f);(1,2,4.0f);(5,6,7.0f);(5,6,8.0f)]
let dict_edges = new Dictionary<int*int,(int*int*float32) list>()
for x in edgelist1 do dict_edges.Add ((fun (a,b,c)-> (a,b)) x, x)
for k in dict_edges.Keys do dict_edges.[k] <- (dict_edges.[k] |> List.rev)
System.InvalidOperationException: Collection was modified; enumeration
operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource
resource) at
System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.MoveNext()
at .$FSI_0101.main#()
individually this is working
dict_edges.[(1,2)] <- dict_edges.[(1,2)] |> List.rev;;
in the for loop i need just to change dictionary values, not keys.
thanks
You can copy all the keys into a temporary list, and then iterate over that list while modifying the original dictionary:
for k in (dict_edges.Keys |> Seq.toList) do
dict_edges.[k] <- (dict_edges.[k] |> List.rev)
But I would strongly advise you to rethink your approach and get rid of in-place mutation. This little problem you're facing right now is only the first taste of what could go wrong with a mutation-based program.
The code you posted is not even syntactically correct, so it's not clear what precisely you are trying to achieve (compiler screams at ((fun (a,b,c)-> (a,b)) x, x) saying that it expects the second x to be a list)
I guess what you are after is: You have a list of weighted edges, where there can be multiple edges between nodes. You'd like to collapse them into a canonical form, where you have all edges grouped that connect any pair of nodes (i,j). Just use any of the groupBy library functions, and you're good:
let map_edges =
edgelist1
|> List.groupBy (fun (a, b, _) -> (a, b))
|> Map.ofList
In the current code you are using ((fun (a,b,c)-> (a,b)) x, x) to extract members of a tuple. Instead, use patterns right in the for expression:
for (a, b, c) in edgelist1 do dict_edges.Add ((a, b), [(a, b, c)])
(I've added [] to make it at least compile)
Note also that you are duplicating information: You store the node tuple in the keys and in the values of the list, making the data structure possibly inconsistent and larger. Consider the following:
let map_edges =
edgelist1
|> List.map (fun (a, b, c) -> (a, b), c)
|> List.groupBy fst
|> List.map (fun (nodeTuple, edgeList) ->
nodeTuple, (edgeList |> List.map snd))
|> Map.ofList
map_edges
|> Map.iter (fun (nodeI, nodeJ) edgeList ->
edgeList
|> Seq.map string
|> String.concat "; "
|> printfn "Nodes (%i, %i): weights %s" nodeI nodeJ
)
(You may want to use sequences as the intermediate representation rather than list)
Wouldn't it be easier to just say dict_edges = dict_edges.map( $0.reverse())
Sorry about the bad f# syntax
Related
I want to add an element to a list. The elements will be created inside of a for loop. What I currently have is
let MaxCubeVolume tpList =
let list1 = []
printfn "%A" list1
for l,w,h in tpList do
let vol = CubeVolume l w h
let list = vol::list1
printfn "%A" list
Where list1 is the main list I am trying to add to, and list is what I am trying to use to add to that list. CubeVolume is working, it takes 3 floats and returns the volume of a cube. tpList is a list of tuples which contain 3 floats. Where I'm lost is how I add the vol to the main list?
F# lists are immutable. You can't "change" them. You don't "add" elements to them. You can only create a new list out of the old one (but the old one remains unchanged and still available for use).
But this is the wrong frame of mind for functional programming. In functional programming you don't compute the result by repeatedly modifying data structures. Instead, you compose larger data structures out of smaller ones, or by using (and composing) primitive functions that do it for you.
In particular, if you have a list of, say, hypothetically, triples, and you have a function that can transform one such triple into, say, hypothetically, a number, and you'd like to make yourself a list of those numbers - that's a very well known primitive operation called map:
let tripleToNumber (l, w, h) = CubeVolume l w h
let list1 = List.map tripleToNumber tpList
Or you can specify the transforming function inline, without giving it a separate name:
let list1 = List.map (fun (l, w, h) -> CubeVolume l w h) tpList
And then you can use the |> operator to rearrange the parameters of List.map, just to make it look a bit nicer:
let list1 = tpList |> List.map (fun (l, w, h) -> CubeVolume l w h)
Or, alternatively, you can use F# list comprehensions, which are syntactic sugar: they're doing the same thing under the hood, but have a (arguably) better look:
let list1 = [for (l, w, h) in tpList -> CubeVolume l w h]
An important thing to note here that neither of the above snippets actually change any data in place. Both of them generate a new datum by transforming an old one.
In addition to Fyodor's answer (which is pretty comprehensive), a general F# solution for what you've named your function (finding the maximum value of the result of a computation of a sequence) would be to compose the map and max functions. These functions exist on the standard F# collection modules (Seq, List, and Array), and you can chain them together using the |> operator:
let maxCubeVolume tpList =
tpList |> Seq.map (fun (l,w,h) -> CubeVolume l w h) |> Seq.max
You could also compose them together using the >> operator instead:
List.map (fun (l,w,h) -> CubeVolume l w h) >> List.max
There's also a built-in function maxBy on the standard F# collections that returns the element in the collection which has the maximum value for a given function. This would return the cube itself (the one with the maximum volume) rather than the computed value for the volume. Here's an example using Seq (the most general of the F# collection types):
let maxCubeVolume tpList =
tpList |> Seq.maxBy (fun (l,w,h) -> CubeVolume l w h)
I am trying to shuffle a list of any a using random numbers. The reason I ask this here is because I have already made a function and I can't figure out why exactly it isn't working.
pick :: [a] -> IO a
pick xs = do
n <- randomRIO (0, length xs - 1)
return $ xs !! n
shuffle :: [a] -> [IO a]
shuffle ls = do
x <- pick ls
let y = remove x ls
(return x) : shuffle y
-- Remove an element from a list (Only first appearance)
remove :: (Eq a) => a -> [a] -> [a]
remove _ [] = []
remove r (x:xs) = if x == r then xs else x : remove r xs
The error I get:
num.hs:31:10: error:
* Couldn't match type `IO' with `[]'
Expected type: [a]
Actual type: IO a
* In a stmt of a 'do' block: x <- pick ls
In the expression:
do x <- pick ls
let y = remove x ls
(return x) : shuffle y
In an equation for `shuffle':
shuffle ls
= do x <- pick ls
let y = ...
(return x) : shuffle y
|
31 | x <- pick ls
| ^^^^^^^
What doesn't make sense to me is that it says it received a type [a] instead of IO a for pick, but ls is defined as [a]?
If there is something fundamentally wrong with this that I just don't understand, is there another way to shuffle a list in Haskell that is this simple? Preferably without any imports.
What's happening is that the type signature for shuffle implies that its do-block has type [IO a]. This means that the monad for this do-block isn't IO as you intend, but rather the monad instance for lists [], as that's the "outermost" type constructor here. The expression pick ls is therefore required, by the do-block, to have type [t] for some type t, but the type signature for pick implies that pick ls has type IO a for some type a. GHC is complaining that it expected pick ls to have a list type [a] (because of the type of the do-block) but its actual type was IO a (because of the type signature of pick).
I believe the conceptual mistake you've made is that you're thinking of IO as a kind of modifier on a type that makes it IO-friendly. So, if IO a is an a that can be generated using an effectful IO computation, then it must be true that [IO a] is a list of as each of which can be generated using an effectful IO computation. But this is wrong!
Instead, you should think of IO a as an IO action (like a recipe) that, when executed, can produce an a. If you want a list of such as, you don't want a list of actions/recipes, each of which produces a single a (i.e., you don't want [IO a]). Instead, you want a single action/recipe that produces a list of as, so you want an IO [a].
So, shuffle should have type signature:
shuffle :: [a] -> IO [a]
Making this change will result in another error for the last expression:
(return x) : shuffle y
The issue here comes from the same conceptual mistake: you're taking a (trivial) action/recipe for generating x and trying to create a list of actions/recipes (though now shuffle y isn't a list anymore, so there's a type mismatch). Instead, you want to replace this with:
xs <- shuffle y -- use `shuffle y :: IO [a]` action to get `xs :: [a]`
return (x:xs) -- make an action to return the whole list (type `IO [a]`)
You'll also find you need to add an Eq a constraint to shuffle because it's required to invoke remove; also, this will hang unless you properly handle the empty list case. The final version of shuffle would be:
shuffle :: (Eq a) => [a] -> IO [a]
shuffle [] = return []
shuffle ls = do
x <- pick ls
let y = remove x ls
xs <- shuffle y
return (x:xs)
and that should work:
> shuffle [1..10]
[6,8,7,2,5,10,1,9,4,3]
You probably are looking for a function like:
shuffle :: [a] -> IO [a]
shuffle [] = return []
shuffle ls = do
x <- pick ls
fmap (x:) (shuffle (remove x ls))
You thus first pick an element from ls and then you recurse on the list of the list. Then we can return a list (x:xs).
The above can made more elegant. I leave this as an exercise. It is for example usually not a good idea to calculate the length of a list each iteration, since that makes the algorithm O(n2). Furthermore you might want to rewrite pick as a function that returns the item and the list after removal.
I am trying to convert a list of tuples(A*B) into a list of (B). How would I approach this? As I ultimately am trying to get the second value from a map so therefore I first turned it into a list but I am struggling removing the first elements from the list as I do not need them.
I got something like this:
map |> Map.toList
now I figured I had to use List.filter but I do not see how to set up a bool expression to evict the 1st values from list so maybe its better to create a entirely new list with the seconds values.
Any help would be appreciated!
Easy:
["a", 1; "b", 2]
|> List.map snd
|> printfn "%A"
Another way:
["a", 1; "b", 2]
|> List.map (fun (a, b) -> b)
|> printfn "%A"
By the way the module Map refers to a different type than List. A Map is an immutable Dictionary: https://msdn.microsoft.com/visualfsharpdocs/conceptual/collections.map%5b%27key%2c%27value%5d-class-%5bfsharp%5d
I need to sort a list that is type
ListToSort val: (string*Seq<string>) list
My idea is to sort this list by the length of the sequence
Im using the commands List.Sortby snd and Seq.Length but I havent been able to make it work..
Any ideas?
thanks
EDIT:
A more Clear idea of the code is (the list that I want to sort is created by Seq.grouby that groups repeated elements in the original list)
let grouped =
OriginalList
|> Seq.groupBy (fun value -> if value = value then value else "else" )
|> Seq.toList
|> Seq.Sortby.... // sort the list by the length of the sequence
Adding the line
|> List.sortBy(fun (_, s) -> Seq.length s) –
Suggusted by vcsjones made it work
let grouped =
OriginalList
|> Seq.groupBy (fun value -> if value = value then value else "else" )
|> Seq.toList
|> List.sortBy(fun (_, s) -> Seq.length s) –
This returned the list sorted!!
is there a way to iterate list over the list through List.map?
I know List.map takes single function and list and produce a list that the function applies to all elements. But what if i have a list of function to apply a list and produce list of the list ?
Your question is not very clear, however as far as I understand it, you have a list of functions and a list of values. If you want to apply all functions to all elements then you can write this:
(* // To get one nested list (of results of all functions) for each element *)
List.map (fun element ->
List.map (fun f -> f element) functions) inputs
(* // To get one nested list (of results for all elements) for each function *)
List.map (fun f ->
List.map (fun element -> f element) inputs) functions
In case this is not what you wanted, could you try clarifying the question a little bit (perhaps some concrete example would help)?
Are you allowed to use List.map2? Because then this is simple:
let lista = [(fun x -> x + 1); (fun x -> x + 2); (fun x -> x + 3)];;
let listb = [1; 1; 1];;
let listc = List.map2 (fun a b -> (a b)) lista listb;;
The output would be [2; 3; 4]
Edit: wait, I think I read your problem wrong. You want to get a list of lists, where each list contains a list of a function applied to the initial list? In other words, for the lista and listb above, you'd get:
[[2;2;2];[3;3;3];[4;4;4]]
Is this correct?
You can try this :
let rec fmap fct_list list = match fct_list with
[] -> //you do nothing or raise sth
head::tail -> List.map head list :: fmap tail list;;