I've got an assigned problem where I have to create a function firstColumn : lst : 'a list list -> 'a list, which takes a list of lists and generates a new list using the first element from each nested list. For example, firstColumn [[343;32];[11;75]] would return a new table [343;11].
So far I've tried using a loop to append each element's head (first element in the nested list) to the new list:
let firstColumn (lst : 'a list list) : 'a list =
let newList = []
for elm in lst do
elm.Head :: newList
newList
However, this results in warning FS0020, where the result of elm.Head :: newList is ignored, and newList's inital empty table is returned.
The implerative solution based on your example posted by Robert works fine. However, if you wanted to follow a functional style, then you can write the same thing using recursion and pattern matching:
let rec firstColumn lst =
match lst with
| (head::_) :: lst -> head :: (firstColumn lst)
| _ -> []
The pattern (head::_) :: lst takes a list of lists, extracts the head of the first list and gives you remaining lists as lst, so you can then recursively process lst and append head to the front as the first column.
I think you just misunderstood the syntax (not much of a misunderstanding, but just enough that you get the wrong result).
Look at this almost similar code, and spot the differences:
let firstColumn (lst : 'a list list) : 'a list =
let mutable newList = []
for elm in lst do
newList <- elm.Head :: newList
List.rev newList
Edit: I realize that Funk already answered almost the same thing, but I thought you might benefit from a more concrete code fix example.
Related
*I edited my original post to include more info.
I'm working on an F# assignment where I'm supposed to create a function that takes an "any list list" as input and outputs an "any list". It should be able to concatenate a list of lists into a single list.
Here's what my function looks like:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
let concat (llst:'a list list) : 'a list =
List.concat llst
List.iter (fun elem -> printf "%d " elem) concat
This solution more or less copied directly from microsofts example of using the List.concat function, the only exception being the specification of input/output types.
When i run the code i get this error:
concat.fsx(7,43): error FS0001: This expression was expected to have type
''a list'
but here has type
''b list list -> 'b list'
So it appears that concat is turning my llst into a character list, which i don't understand.
Can anyone help me understand why I'm getting this type error and how I can write a function that takes the types that I need?
The problem is somewhere in your implementation of the concat function. It is hard to say where exactly without seeing your code, but since this is an assignment, it is actually perhaps better to explain what the error message is telling you, so that you can find the issue yourself.
The error message is telling you that the F# type inference algorithm found a place in your code where the actual type of what you wrote does not match the type that is expected in that location. It also tells you what the two mismatching types are. For example, say you write something like this:
let concat (llst:'a list list) : 'a list =
llst
You will get the error you are getting on the second line, because the type of llst is 'a list list (the compiler knows this from the type annotation you give on line 1), but the expected type is the same as the result type of the function which is 'a list - also specified by your type annotation.
So, to help you find the issue - look at the exact place where you are getting an error and try to infer why compiler thinks that the actual type is 'a list list and try to understand why it expects 'a list as the type that should be in this place.
This is correct:
let concat (llst:'a list list) : 'a list =
List.concat llst
However, it's really equivalent to let concat = List.concat
This, however, doesn't compile, the elements of the lists need to be of the same type:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
This also is problematic:
List.iter (fun elem -> printf "%d " elem) concat
List.iter has two arguments and the second one needs to be a List. However in your case you are (as per compiler error) providing your concat function which is a a' List List -> a' List.
What I suspect you meant to do, is apply the concat function to your llist first:
List.iter (fun elem -> printf "%d " elem) (concat llist)
// or
llist
|> concat
|> List.iter (fun elem -> printf "%d " elem)
However, all of this is perhaps missing the point of the exercise. What perhaps you need to do is implement some simple recursion based on the empty / non-empty state of your list, ie. fill in the blanks from here:
let rec myconcat acc inlist =
match inlist with
| [] -> ??
| elt :: tail -> ??
Given this tree type:
type T<'a> = N of 'a * T<'a> list
which could be declared as:
let ta = N("b", [N("c", [])])
How would I get all the possible paths in this tree? I've tried by applying the method mentioned in this post, but it just returns an empty list. This is how I've implemented it:
let rec isPath is t =
match t with
| N(x, t) -> List.collect (isPath (x::is)) t
isPath [] ta |> (printf "isPath: %A")
but it only returns isPath: []. What am I doing wrong? My secondary goal would then be to make a second function where I can pass a list of ints to check if there are any paths that correspond to this list.
You need another match condition that catches empty lists and doesn't iterate through them. Right now your List.collect, when t is empty, is iterating through an empty list and is therefore returning an empty list to the "previous" level of your recursive function. Which is then appending all those empty lists together to get... an empty list, and so on.
Add the following match case and you should get what you need:
| N(x, []) -> is
Note that this should come before your other match case in order to work: since F# processes match cases from top to bottom, N(x, t) will match anything, and N(x, []) won't ever be checked if it's second.
So you want your function to look like:
let rec isPath is t =
match t with
| N(x, []) -> is
| N(x, t) -> List.collect (isPath (x::is)) t
Again, if you don't see why this works, let me know and I'll explain further.
I'm curious as to how the list module/type works in F#, specifically does it optimise this?
let xs = ["1"; "2"; "3"]
let ys = "0"::xs
let zs = ["hello"; "world"]#xs
I've looked over some of the source https://github.com/fsharp/fsharp/blob/68e37d03dfc15f8105aeb0ac70b846f82b364901/src/fsharp/FSharp.Core/prim-types.fs#L3493 seems to be the relevant area.
I would like to know if xs is copied when making ys.
I would have thought it's easy to just point to the existing list if you just cons element.
If you are concatenating I imagine it might be impossible as it would require mutating the last element of the list to point to the next one?
If someone could annotate/paste snippets of code from FSharp.Core that would be ideal.
So the implementation of List is a little odd. It is actually implemented as a discriminated union. From the spec:
type 'T list =
| ([])
| (::) of 'T * 'T list
So you can think of :: as a function that takes two arguments and creates a tuple (which is fast as it is independent of the list size).
# is much more complicated. Here is the implementation:
let (#) l1 l2 =
match l1 with
| [] -> l2
| (h::t) ->
match l2 with
| [] -> l1
| _ ->
let res = [h]
let lastCons = PrivateListHelpers.appendToFreshConsTail res t
PrivateListHelpers.setFreshConsTail lastCons l2;
res
The two weird functions basically mutate the list in place. appendToFreshConsTail copies the list and returns the last element. setFreshConsTail then changes the last element so that its next element is set to l2 rather than [] joining the lists.
I am not sure if this is a stupid question, but I was doing some simple problems on lists in F#. I am unable to handle nested lists. My question is, Why I can't pass a nested list when I have declared a list as parameter of a function? I mean the nested list is also a list. What is the advantage of differentiating lists of simple int or char from lists of lists?
If a function is generic and takes a parameter 'a list, the type of 'a could also be a list. So the function would work with lists, or lists of lists, or lists of lists of lists, ...so long as the outer type is a list, 'a could be anything.
For example:
let isNonEmpty = function
| [] -> false
| _::_ -> true
isNonEmpty [1; 2; 3]
isNonEmpty [[1]; [2]; [3]]
If your function doesn't depend on the list elements being of a certain type it should probably be generic. If you post your code perhaps someone can help with that.
EDIT
A naive version of your flatten function, without using built-in functions, might be:
let flatten lst =
let rec helper = function
| [] -> []
| h::tl ->
match h with
| Elem x -> x::helper tl
| List xs -> helper xs # helper tl
helper [lst]
If you have a function requiring a list<char> and you have a list<list<char>> those types don't match. However, there is a function List.concat which will "flatten" the list of lists.
So:
let list = [ ['a'] ; ['b'] ]
let list' = list |> List.concat // [ 'a' ; 'b' ]
For anyone who is looking for more of a dynamically typed nested list behavior, you should take a look at my NestedPair module:
https://gist.github.com/calebh/45871d3d40dc93526b3fd227cd577467
This module allows for "lists" of arbitrary depth by using a simple wrapper type.
Hey guys, I'm trying to get cozy with functional programming (particularly with F#), and I've hit a wall when it comes to building tail-recursive functions. I'm pretty good with turning basic recursion (where the function basically calls itself once per invocation), into tail recursion, but I now have a slightly more complicated situation.
In my case, the function must accept a single list as a parameter. When the function is called, I have to remove the first element from the list, and then recur using the remainder of the list. Then I need to apply the first element which I removed in some way to the result of the recursion. Next, I remove the second element and do the same thing (Note: when I say "remove the seond element", that is from the original list, so the list passed at the recursion includes the first element as well). I do the same for the third, fourth, etc. elements of the list.
Is there a way to convert the above situation into a tail-recursive function? Maybe nested tail-recursive functions??? Thank you for any answers.
Okay, so here's my basic code. This particular one is a permutation generator (I'm not too concern with the permutation part, though - it's the recursion I'd like to focusing on):
let permutationsOther str =
match str with
| value :: [] ->
[[value]]
| _ ->
let list = (List.map (fun a -> // This applies the remove part for every element a
let lst = (List.filter (fun b -> b <> a) str) // This part removes element a from the list
let permutedLst = permutations lst // recursive call
consToAll a permutedLst // constToAll this is my own function which performs "cons" operation with a and every element in the list permutedLst
) str)
List.reduce (fun acc elem -> elem # acc) list // flatten list of lists produce by map into a single list
I hope this is clear enough - I'll be happy to provide clarifications if needed.
By the way, I have found just a way to rewrite this particular function so that it only uses a single recursion, but it was a fluke more than an informed decision. However, this has encouraged me that there may be a general method of turning multiple recursion into single recursion, but I have not yet found it.
Conversion to CPS should do the trick:
NOTE 1: Source of the sample is typed directly in browser, so may contain errors :(. But I hope it can demonstrate the general idea.
NOTE 2: consToAll function should be converted to CPS too: consToAll: 'T -> 'T list list -> ('T list list -> 'R) -> 'R
let remove x l = List.filter ((<>) x) l // from original post: should duplicates also be removed ???
let permute l =
let rec loop k l =
match l with
| [] -> k []
| [value] -> k [[value]]
| _ -> filter l [] l (fun r -> r |> List.reduce (fun acc elem -> elem # acc) |> k )
and filter l acc orig fk =
match l with
| [] -> fk acc
| x::xs ->
remove x orig
|> loop (fun res ->
consToAll x res (fun rs -> filter xs (rs::acc) orig fk)
)
loop id l