Haskell head/tail vs pattern matching - haskell

Here are two pieces of code.
Working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins xs d = head xs ++ d ++ (joins (tail xs) d)
Not working:
joins :: [String] -> String -> String
joins [] _ = ""
joins [x] _ = x
joins [x:xs] d = x ++ d ++ (joins xs d)
The error log for the latter is:
test.hs:4:18:
Couldn't match expected type `[Char]' with actual type `Char'
In the first argument of `(++)', namely `x'
In the expression: x ++ d ++ (joins xs d)
In an equation for `joins':
joins [x : xs] d = x ++ d ++ (joins xs d)
test.hs:4:35:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: [Char]
In the first argument of `joins', namely `xs'
In the second argument of `(++)', namely `(joins xs d)'
In the second argument of `(++)', namely `d ++ (joins xs d)'
What am I missing here?

Use parentheses, not brackets:
-- vvvvvv
joins (x:xs) d = x ++ d ++ (joins xs d)
The pattern [x:xs] matches only with a list of length one, whose single element is a nonempty list x:xs.
Since yours is a list of strings, [x:xs] matches with ["banana"] (where x='b', xs="anana"), with ["a"] (x='a', xs="") but not with ["banana", "split"] nor with [""].
This is clearly not what you want, so use plain parentheses.
(By the way, the parentheses in ... ++ (joins xs d) are not needed: function application binds more than any binary operator in Haskell.)

Related

How to delete spaces in string and write first letter uppercase?

I am trying to delete every space between words and uppercase every letter of a word with foldr.
I have tried it with map:
deleteSpaces:: String -> String
deleteSpaces word = (filter(not . isSpace) .unwords . map (\(x:xs) -> (toUpper x):xs) . words) word
it works.
But with foldr I always get an error:
deleteSpacesF :: String -> String
deleteSpacesF word = (filter(not . isSpace) . unwords . foldr (\(x:xs) acc -> (toUpper x) : xs : acc) [] . words) word
I have also tried (\x acc -> (toUpper (head x)):(tail x):acc)
The error is:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected: String
Actual: Char
• In the first argument of ‘(:)’, namely ‘(toUpper x)’
In the expression: (toUpper x) : xs : acc
In the first argument of ‘foldr’, namely
‘(\ (x : xs) acc -> (toUpper x) : xs : acc)’
x is a Char, not a String, so head x and tail x, make no sense. You use x as the head and xs as the tail, so.
Here it thus looks like:
deleteSpacesF :: String -> String
deleteSpacesF = concat . foldr (\(x:xs) -> ((toUpper x : xs) :)) [] . words
you can also omit the concat with:
deleteSpacesF :: String -> String
deleteSpacesF = foldr (\(x:xs) -> (toUpper x :) . (xs ++)) [] . words
You could do something like this:
process = concat . map cap . words
where
cap [] = []
cap (x:xs) = (toUpper x):xs
This defines a helper function to capitalise the first letter, which can then be mapped over each word derived from splitting the original string.
Note that words will also treat tabs and newlines as separators along with regular spaces, so you may need to modify that if you only care about space characters.

Haskell in append few list together

I want to the value of one element in a List , So I did the
changePoint :: (Int,Int) -> [[[Char]]] -> [[Char]]
changePoint (x,y) maze = let
linelement = maze !! (y-1)
-- value ["X"," "," ",...," ","X"]
rowelement = chunksOf 1 $ head linelement
-- type:[[a]]; value ["X"," "," "," "," "," "," "," "," "," "," "," "," ","X"]
l = length rowelement
list = take (x-1) rowelement
-- in take (x-1) rowelement -- ["X"]
in take (x-1) rowelement ++ (["."] : (drop (x) rowelement))
I want to append the list "take (x-1) rowelement" and "["."]" and "drop (x) rowelement", the type of list will be [[a]]
Couldn't match expected type ‘Char’ with actual type ‘[Char]’
In the expression: "."
In the first argument of ‘(:)’, namely ‘["."]’
In the second argument of ‘(++)’, namely
‘(["."] : (drop (x) rowelement))’ Failed, modules loaded: none.
x = 2 .
I know the problem is "["."]",but I really don't how to fix it .
The true return should be ["X","."," "," ",..,"X" ]
In GHCI, you can use :t somefunction to get the type of somefunction.
Here, the problem is with (:), lets see what GHCI tells us.
Prelude λ> :t (:)
(:) :: a -> [a] -> [a]
So (:) takes an a, a list of as and returns a new list. Specialized for the use case at hand, (:) has type [Char] -> [[Char]] -> [[Char]] (because a = [Char]). But ["."] has type [[Char]], so it does not match what's expected for (:).
Now, if you use take (x-1) rowelement ++ ("." : (drop (x) rowelement)) (note the missing [] around "."), the function should compile fine.
Either use:
(take (x-1) rowelement) ++ ["."] ++ (drop x rowelement)
Or
(take (x-1) rowelement) ++ ("." : (drop x rowelement))
The [ and ] are not necessary

Filtering on a List of Tuples

I'm trying to filter a list of 2-tuples where the first tuple value equals 0:
ghci> ys
[(0,55),(1,100)]
ghci> filter (\x -> x.fst == 0) ys
<interactive>:71:27:
Couldn't match type `(Integer, Integer)' with `b0 -> c0'
Expected type: [b0 -> c0]
Actual type: [(Integer, Integer)]
In the second argument of `filter', namely `ys'
In the expression: filter (\ x -> x . fst == 0) ys
In an equation for `it': it = filter (\ x -> x . fst == 0) ys
My desired output:
[(1,100)]
How can I achieve this? Also, what does the compile-time error mean?
(.) is function composition, you want filter (\x -> fst x == 0) ys.
Edit: you actually want filter (\x -> fst x /= 0) ys because filter provides a list of values that satisfy the predicate.
The compile time error is complaining because the compiler infers that x must be a function because you're composing it with fst, but ys is not a list of functions.

Couldn't match expected type

I have the following Haskell program:
catlines = unlines . zipWith (\(n,l) -> show n ++ l) [0..]
main = putStrLn $ catlines ["A", "B"]
When I try to compile it, GHC gives the following error:
catlines.hs:1:41:
Couldn't match expected type `b0 -> String' with actual type `[a0]'
In the expression: show n ++ l
In the first argument of `zipWith', namely
`(\ (n, l) -> show n ++ l)'
In the second argument of `(.)', namely
`zipWith (\ (n, l) -> show n ++ l) [0 .. ]'
From what I know, this should compile. I have no idea what's wrong.
The problem is that the function passed to zipWith should take two arguments, not a tuple. Try it like this:
zipWith (\n l -> show n ++ l)

++ operator with String and IO String

explandDol :: String -> String -> [String] -> IO String
explandDol conclusion operators atoms =
let (ys,zs) = splitAt (head (take 1 replacement)) conclusion in ys ++ getConclusion operators atoms ++ (tail zs)
where replacement = elemIndices '$' conclusion
getConclusion :: String -> [String] -> IO String
getConclusion operators atoms =
runRVar (choice [atom1 ++ " " ++ [operator] ++ " " ++ atom2 | atom1 <- atoms, atom2 <- atoms, operator <- operators,checkAtoms atom1 atom2]) StdRandom
Is there a good way to fix this? I am getting this error:
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 69:
Couldn't match expected type `IO String' with actual type `[Char]'
In the expression: ys ++ getConclusion operators atoms ++ (tail zs)
In the expression:
let (ys, zs) = splitAt (head (take 1 replacement)) conclusion
in ys ++ getConclusion operators atoms ++ (tail zs)
In an equation for `explandDol':
explandDol conclusion operators atoms
= let (ys, zs) = splitAt (head (take 1 replacement)) conclusion
in ys ++ getConclusion operators atoms ++ (tail zs)
where
replacement = elemIndices '$' conclusion
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 75:
Couldn't match expected type `[Char]' with actual type `IO String'
In the return type of a call of `getConclusion'
In the first argument of `(++)', namely
`getConclusion operators atoms'
In the second argument of `(++)', namely
`getConclusion operators atoms ++ (tail zs)'
/home/joe/Documents/haskell/LAG/main/main.hs: line 73, column 75:
Warning: Redundant bracket
Found:
getConclusion operators atoms ++ (tail zs)
Why not:
getConclusion operators atoms ++ tail zs
Because value returned by getConclusion is IO String you cannot simply use it with functions operating on unwrapped values. Either first unwrap value using x <- getConclusion operators atom or if you want function composition use fmap.

Resources