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 :)
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.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a list of tuples containing information in the following form as so:
carDatabase :: [Car]
carDatabase = [("Ford", "Focus", 2003, [("Autotrader", 9995), ("Parkers", 9495), ("Motors", 9995)]), ("Vauxhall", "Corsa", 2005, [("Autotrader", 5995), ("FOW", 7000), ("Gumtree", 6500)]), ...]
And what I am trying to do is map this list to return a list of strings with the first element of each tuple (I have a function that does this with carMan (x,_,_,_) = x) but also using the toLower function and I cannot work out a way to combine them, be it with function compositions or mapping a map etc.
This is the closest I've got.
mapTest :: [Car] -> [String]
mapTest cs = map toLower (map carMan cs)
Any help would be appreciated.
This is the error I get with:
mapTest :: [Car] -> [String]
mapTest cs = map (toLower . carMan) cs
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: Char -> String
Actual type: Char -> Char
In the first argument of ‘(.)’, namely ‘toLower’
In the first argument of ‘map’, namely ‘(toLower . carMan)’
cars.hs:197:37:
Couldn't match type ‘[Char]’ with ‘Char’
Expected type: [(Char, String, Int, [(String, Int)])]
Actual type: [Car]
In the second argument of ‘map’, namely ‘cs’
In the expression: map (toLower . carMan) cs
You can do this with function composition using .
map ((map toLower) . carMan) cs
Or make it a helper function:
strLower :: String -> String
strLower = map toLower
mapTest :: [Car] -> [String]
mapTest = map (strLower . carMan)
I'm a Haskell beginner and I'm wrestling using functions to modify a list and then return it back to a string. I'm running into this error however. Any advice?
Couldn't match type 'Char' with '[Char]'
Expected type: String
Actual type: Char
createIndex:: String -> String
createIndex str = unLine (removeT (splitLines str))
splitLines:: String -> [String]
splitLines splitStr = lines splitStr
removeT:: [String] -> [String]
removeT strT = filter (=='t') strT
unLine:: [String] -> String
unLine unLinedStr = unlines unLinedStr
The problem is in your definition of removeT. The type of removeT is [String] -> [String], meaning it works on a list of lists of characters. Then, in your filter, you compare each list of characters (i.e., each String in the list) to a Char ('t'). This is not allowed (you cannot check values with different types for equality).
How to change your code really depends on what you intend to do. It's not entirely clear if you want to remove lines containing t's, if you want to keep lines containing t's, if you want to remove t's, or if you want to keep t's. Depending on what you want to achieve, your code will have to be modified accordingly.
Some pointers:
If you change the type of removeT to String -> String you can look at one line at a time. You would then have to replace removeT in the definition of createIndex by map removeT (because you're applying the function to each line)). In this case, the filter would deal with Char values so comparing with a 't' is allowed.
If you want to do something with lines containing t's, (== 't') is not the way to go, you will want to use ('t' `elem`) (meaning "'t' is an element of").
filter keeps elements matching the predicate. So if you want to remove t's from a string for example, you use filter (/= 't').
print $ concat ["abc", "bde"]
prints
abcbde
whereas,
print . concat ["abc", "bde"]
The error thrown in second case is,
Couldn't match expected type ‘a -> b0’ with actual type ‘[Char]’
Relevant bindings include
it :: a -> IO () (bound at <interactive>:3:1)
Possible cause: ‘concat’ is applied to too many arguments
. (function-composition operator) is used because i thought it will take the output of concat function and pass it to the preceding function print? What is wrong in the code?
Just precedence, really; this will work fine:
(print . concat) ["abc", "bde"]
. composes two functions to create a new function, whereas $ is just a way of avoiding parentheses in this context.
I'm having a lot of trouble getting this function to work:
concatenate :: [String] -> String
It is designed to simply take a list of strings and return a single string that is the result of the concatenations of each element of the list from head to tail. I'm trying to stay within the map, foldl, and foldr functions. I feel like I know what the concept of these functions do well enough, but the most common problem I'm running into is that I'm having a conflict of types. GHC will expect a [Char] for example, and I'll put in code that is apparently trying to use a [[Char]] without me knowing it.
For example: concatenate (x:xs) = foldr (++) x (concatenate xs)
And I get the following compile error:
Couldn't match type `Char' with `[Char]'
Expected type: [[Char]]
Actual type: String
In the return type of a call of `concatenate'
In the third argument of `foldr', namely `(concatenate xs)'
In the expression: foldr (++) x (concatenate xs)
I'm very new to Haskell, so please feel free to laugh. Harshness is expected, and welcomed, as long as an explanation fit for a newbie is also included. Thank you for any and all help.
You actually don't need the recursive call there. The function foldr already simulates a recursive call. All you need to do is use:
concatenate :: [String] -> String
concatenate ls = foldr (++) "" ls
And remember that there's a concat function already, which is more generic, as it works on any list of list (as opposed to simply list of strings).
I've got this simple function:
bombplaces::Int->[(Int,Int)]->[(Int,Int)]
bombplaces bombCount listOfPossiblePoints = nub (map (take bombCount) (perms listOfPossiblePoints))
bombs are (x,y) (carthesian points)
i need to get an all permutations and take only first few (bombCount) points.
I'm getting following error:
Couldn't match expected type `(Int,Int)' with actual type `[a0]'
Expected type: [a0] -> (Int,Int)
Actual type: [a0] -> [a0]
In the return type of a call of `take'
In the first argument of `map', namely `(take liczbaBomb)'
If you remove the type signature and ask GHCi for the type, your problem will be obvious:
> :t bombplaces
bombplaces :: Eq a => Int -> [a] -> [[a]]
That is, bombplaces wants to return a list of lists whereas you want it to return a plain list. You need to either change the type signature, or change the definition of the function, depending on what you want the behaviour to be.
N.B. You didn't tell us what definition of perms you are using, so I assumed the obvious one.