0

I'm trying to use the map function in haskell

I've got this:

lexi :: String -> [[String]]
lexi x = map (words.lines) x

I want to be able to put a string in to x, so it can be run like this

lexi ("string here")

But get the error

Couldn't match type ‘[Char]’ with ‘Char’
Expected type: String -> String
  Actual type: String -> [String]
In the second argument of ‘(.)’, namely ‘lines’
In the first argument of ‘map’, namely ‘(words . lines)’

Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
  Actual type: String
In the second argument of ‘map’, namely ‘x’
In the expression: map (words . lines) x

I know that if I use

lexi = map (words.lines) 

it works fine when I run lexi ("string here"), but need the variable to use later on

Could some please explain why this doesn't work and how to fix it?

Thank you :)

6
  • 2
    What is the type of function? is it Char -> Char or Char -> String? Commented Nov 17, 2014 at 11:38
  • I want it to take a String, and the function that is being used in the map will return a [String] Commented Nov 17, 2014 at 11:40
  • if function has type String -> [String] then map function will have type [String] -> [[String]]. Are you sure you want map? Commented Nov 17, 2014 at 11:43
  • I've updated the question to try and make it clearer Commented Nov 17, 2014 at 11:46
  • What do you want lexi to do? Commented Nov 17, 2014 at 11:48

1 Answer 1

4

This answer refers to an old version of the question.

So let's get this quite clear (please always add the type signature of all functions you're talking about!)

function :: Char -> [String]

Well, then the type of map function is [Char] -> [[String]], i.e. String -> [[String]]. But you want the result to be only [String], not a triply-nested list. You probably want to join the lists of two levels together; in general the function to use for list-joining purposes is concat (or more generally, join from the Control.Monad module). In this case, you have two different options:

  • Join the result of each call to function. I.e., instead of mapping function alone, you map join . function, which has type Char -> String. Mapping that has the desired type String -> [String].

    lexi = map $ join . function
    
  • Join the final result of the mapping, i.e. lexi = join . map function. This combination of mapping and joining the results is actually an extremely common task, it has a special operator: monadic bind!

    lexi x = x >>= function
    

New version

So we know that

words, lines :: String -> [String]

thus words . lines can not work, because you're trying to feed a list of strings into a function that only accepts a single string. What you can of course do though is map words over the result, i.e. map words . lines. That has in fact the correct signature and probably does just what you want.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the answer! Just a few questions, is the >>= operator assigning the function to x? And the join function, turns the double list into a single list? Also I've made my question clearer now, so sorry about the initial ambiguity
That edit unfortunately changed the meaning of the entire question. Please try to avoid this kind of confusion in the future. — The >>= works kind of like a swapped $ function-application operator. We can actually write it the other way around: f =<< list ≡ join (map f list) i.e. it'll first map f over the list, then join the results together.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.