Fsharp noob
Fsharp noob

Reputation: 19

Why does F# not like the type ('a list list) as input?

*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?

Upvotes: 1

Views: 167

Answers (2)

caspar
caspar

Reputation: 11

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 -> ??

Upvotes: 0

Tomas Petricek
Tomas Petricek

Reputation: 243051

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.

Upvotes: 3

Related Questions