Reputation: 23
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 :)
Upvotes: 0
Views: 3381
Reputation: 120751
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
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.
Upvotes: 4