Charana
Charana

Reputation: 1072

type signature for a function that makes a list of lists?

bundle :: Int -> [a] -> [[a]]
bundle 0 _ = []
bundle n (x:xs) = [x:bundle (n-1) xs]

My goal is to do something like this

bundle 3 [1,2,3,4,5] = [[1,2,3]]

The code is giving me the error

Couldn't match expected type ‘[a]’ with actual type ‘a’
  ‘a’ is a rigid type variable bound by
      the type signature for bundle :: Int -> [a] -> [[a]]

Upvotes: 1

Views: 214

Answers (2)

chi
chi

Reputation: 116139

bundle :: Int -> [a] -> [[a]]
bundle 0 _ = []
bundle n (x:xs) = [x:bundle (n-1) xs]

bundle (n-1) xs has type [[a]]. For x : bundle (n-1) xs to make sense, x must be an element of [[a]], so it must be an [a]. But it is simply an a.

In other words, you are attempting to build an ill-formed list such as

[ 1 , [2,3] , [4,5] ]
  ^-- not a list

Do you really want to build a [[a]]? Isn't an [a] more appropriate for your goal?

Upvotes: 3

Random Dev
Random Dev

Reputation: 52280

Chi wrote a bit about the problem - I start at your example and see where it leads me.

I honestly don't understand why you want the second warping but the easiest way you can get this going would be:

bundle :: Int -> [a] -> [[a]]
bundle 0 _ = [[]]
bundle n (x:xs) = let [xs'] = bundle (n-1) xs in [x : xs']

of course this will give you [[]] for ´bundle 0 ...` but I think that's indeed what you want

Now of course there are some easier ways - for example there is already a function that does something similar: take - it just does not wrap the second time but this you can do with a simple return:

bundle :: Int -> [a] -> [[a]]
bundle n = return . take n

Upvotes: 1

Related Questions