Dominik Seibold
Dominik Seibold

Reputation: 21

Haskell: applying a function with multiple arguments using Map

i want something like that:

helpPadNumbers ["123","45","1"] 4

the result should be: ["#123","##45","###1"] instead of '#' it should be ' ' (space) After my method all elements have the same length.

helpPadNumbers :: [String] -> Int -> [String]
helpPadNumbers x 0 = x
helpPadNumbers x a = map ((test1 x a) a)

test1 :: String -> Int -> String
test1 x a = (spaces1 ((a-length x))) ++ x

spaces1 :: Int -> String
spaces1 0 = ""
spaces1 n = " " ++ spaces1 (n-1)

My problem is: How can i get every single element of the list separately with the map function?

Error: "Probable cause: ‘map’ is applied to too few arguments"

is there a way to fix that problem?

Upvotes: 2

Views: 3909

Answers (1)

Random Dev
Random Dev

Reputation: 52290

You are on the right track there - map does indeed what you want. So let's start with a working version for a quick answer:

helpPadNumbers :: [String] -> Int -> [String]
helpPadNumbers x 0 = x
helpPadNumbers x a = map (\ xs -> test1 xs a) x

have a look at the map there - your problem was basically the order and the parens.

making it look nicer

Of course that's not really Haskell style so let's reorder your arguments a bit (and remove some parens):

helpPadNumbers :: Int -> [String] -> [String]
helpPadNumbers 0 xs = xs
helpPadNumbers a xs = map (test1 a) xs

test1 :: Int -> String -> String
test1 a x = spaces1 (a - length x) ++ x

spaces1 :: Int -> String
spaces1 0 = ""
spaces1 n = " " ++ spaces1 (n-1)

as you can see this version make use of partial application and we don't need the lambda-expression in there. Also it looks nicer IMO

(++) is not your friend

Have a look at space1 - all you do is prepend a single space character but using lists and cocatenation - not really needed:

spaces1 :: Int -> String
spaces1 0 = ""
spaces1 n = ' ' : spaces1 (n-1)

as you can see this one uses (:) to prepend a single space character ' ' which is more performant.

Speaking of space1: there already is a function for this: replicate:

spaces1 :: Int -> String
spaces1 n = replicate n ' ' 

some further simplifications

replicate is rather forgiving (no problem with negative numbers or zero) - we don't really need the case where a = 0 above. So we can simplify further to this:

helpPadNumbers :: Int -> [String] -> [String]
helpPadNumbers n xs = map (test1 n) xs

test1 :: Int -> String -> String
test1 n x = spaces1 (n - length x) ++ x

spaces1 :: Int -> String
spaces1 n = replicate n ' ' 

and I think we can fit the helper functions into a where clause:

helpPadNumbers :: Int -> [String] -> [String]
helpPadNumbers n = map spaces
  where spaces xs = replicate (n - length xs) ' ' ++ xs
example:

here is an example-use of the last version:

λ> helpPadNumbers 4 ["12345", "1234","123","12","1",""]
["12345","1234"," 123","  12","   1","    "]

Upvotes: 9

Related Questions