Haskell char quotes - haskell

I've started to learn haskell for real recently, and I'm doing some exercises from wikibooks.
I'm doing exercise with RLE encoding, and I've come with solution like this:
import Data.List
rle :: String -> [(Int,Char)]
rle [] = []
rle xs = zip lengths chars
where
groups = group xs
lengths = map length groups
chars = map head groups
rle_toString :: [(Int, Char)] -> String
rle_toString [] = []
rle_toString (x:xs) = show (fst x ) ++ show (snd x) ++ rle_toString xs`
Not a very elegant solution, but it almost works. The problem is, that I get output like this: "7'a'8'b'7'j'6'q'3'i'7'q'1'p'1'a'16'z'2'n'". The single quotes with chars are not vetry elegant. How can I achieve output like: "7a8b7j6q3i7q1p1a16z2n"?

show is used to print values as they appear in Haskell source code, and thus puts single quotes around characters (and double quotes around strings, and so on). Use [snd x] instead to show just the character.
In Haskell, String is just shorthand for List of Char [Char]. For example, the String "Foo" can also be written like this: ['F','o','o']. So, to convert a single character to a string, just put in in brackets: [char].

The problem is your use of show on a character. show 'a' == "'a'".
The solution is to realize that strings are just lists of characters, so if c is a character, then the one-character string that contains c is just [c].

Related

How to delete "Just" in Maybe String or Maybe Int in Haskell

i am new to haskell and in need of a little help with a problem. I have a XML file and i want to parse two things in it. One is a pair of numbers, and the second is just a letter. I use two functions to parse each element, and the result of that functions has to be "Maybe String", or else it won't work.
The problem is, that when i display the result it allways has a "Just" attached to it. So if i want to display something like (1,2) and B
I will have (Just "1", Just "2") and Just "B"
For the numbers i got the solution. I have made this function to work with the list i get from the parse of the pairs:
pair:: [(Maybe String, Maybe String)] -> [(Int, Int)]
pair [] = []
pair ((Just x, Just y) : ls) = (read x, read y) : pair ls
It works fine. But i tried to do the same for the list with the letters and it doesn't work.
here is my code:
letter :: [Maybe String] -> [Char]
letter [] = []
letter (Just x : ls) = read x : letter ls
When i run this, i get the list of pairs right and this error
myfile.hs: Prelude.read: no parse
Why is this happening? Is the read function the problem?
The read parser for Char expects the character to be surrounded in single quotes, i.e. you need a string like "'M'".
Prelude> read "M" :: Char
*** Exception: Prelude.read: no parse
Prelude> read "'M'" :: Char
'M'
You probably want to do something like
letter :: [Maybe String] -> [Char]
letter [] = []
letter (Just [x] : ls) = x : letter ls
However, this of course only works if you always get just Just values and no Nothing values and all strings must have a length of one or the pattern match will fail.
Change your definition of letter to:
letter :: [Maybe String] -> [Char]
letter [] = []
letter (Just x : ls) = (head x) : letter ls
Explanation: read will try to read the content of string as an Haskell Char literal. Since Char literals in Haskell are terminated by quotes, your strings would need to include them (i.e: read "'B'" :: Char works, read "B" :: Char does not).

Haskell: trim String and eliminate multiple spaces

I have just started programming with Haskell and would like to do a String transformation.
I have an arbitrary String e.g.
" abcd \n dad "
I would like to remove the whitespace characters on the left and on the right. And I would like to eliminate multiple whitespaces as well as escape sequcences " \n " -> " "
So the String above would look like this
"abcd dad"
I have already written a function that trims the String and removes the whitespace characters (I'm removing the character if isSpace is true):
trim :: [Char] -> [Char]
trim x = dropWhileEnd isSpace (dropWhile isSpace x)
Now my idea is to do a pattern matching on the input String. But how do I apply the trim function directly to the input? So at first I would like to trim the String at both ends and then apply a pattern matching. So the only thing I would have to do is comparing two characters and removing one if both are whitespace characters
--How do I apply trim directly to the input
s :: [Char] -> [Char]
s [x] = [x]
s(x:xx) = ...
Note: Efficiency is not important. I would like to learn the concepts of pattern matching and understand how Haskell works.
Cheers
trim = unwords . words
Examine the source of words in the Prelude.
If you want to pattern-match on the output of trim, you have to call trim, of course! For example, if you want cases for lists of length 0, 1, and longer, you could use
s xs = case trim xs of
[] -> ...
[x] -> ...
x:x':xs -> ...
Your first pattern matches a single character and returns it. Surely this is not what you want - it could be whitespace. Your first match should be the empty list.
If you were only removing space chars, you could do something like this:
trim :: [Char] -> [Char]
trim [] = []
trim (' ':xs) = trim xs
...
You should be able to see that this removes all leading spaces. At this point, either the string is empty (and matches the first pattern) or it falls through to... leaving that up to you.
If you want to remove all whitespace, you need a list or set of those characters. That might look like this:
trim :: [Char] -> [Char]
trim = let whitespace = [' ', '\t\, `\v'] -- There are more than this, of course
in t
where
t [] = []
t (x:xs) | elem x whitespace = t xs
| otherwise = ...
Again, this has shown how to match the beginning part of the string. Leave it up to you to think about getting to the end.
You can also do pattern matching in a nested function:
s str = removeInnerSpaces (trim str)
where
removeInnerSpaces [] = []
removeInnerSpaces (x:xs) = ...
Here removeInnerSpaces is a nested function, local to s.

Strip left/right a string (and chomp)

I have found nothing about how to strip a string (remove leading/trailing characters) in Haskell, and there’s no place place to find such a strip or chomp function (correct me if I’m wrong).
What am I gonna do?
Have a look at Data.Text. Anything that uses Prelude lists, such as Strings, usually performs poorly, especially with functions like stripR. Some consider it a mistake from the past, because it has infected a lot of (otherwise sensible) interfaces with the inefficiencies of using singly linked lists of characters (String) for textual data.
The functions you're looking for are, in order: dropWhile, dropWhileEnd, dropAround, stripStart, stripEnd, strip.
Note that there's no specific function for stripping based on character equality. You don't really gain anything from aliasing dropX with a predicate, unless it's a very commonly used one like Data.Char.isSpace.
First off, you should use Text (from the text package) instead of String, since text is much more efficient.
Also, text already has this function:
-- Remove leading and trailing white space from a string.
strip :: Text -> Text
The more general approach would be to pass a predicate to the strip functions, so one could stripL isSpace e.g. to remove all leading white space.
Then stripL would however just be an alias for dropWhile.
For the stripping of the end, a potentially more efficient version uses foldr,
stripR :: (a -> Bool) -> [a] -> [a]
stripR pred = foldr keepOrDrop []
where
keepOrDrop c xs
| pred c = case xs of
[] -> []
_ -> c:xs
| otherwise = c:xs
that can start producing output without traversing the entire input list, and is efficient if there are no long runs of elements satisfying the predicate it the input.
Here are 3 functions and 3 currified aliased functions to make it through:
stripL :: Char -> String -> String
stripL x = dropWhile (==x)
stripR :: Char -> String -> String
stripR x = reverse . stripL . reverse
strip :: Char -> String -> String
strip x = stripL x . stripR x
chompL :: String -> String
chompL = stripL ' '
chompR :: String -> String
chompR = stripR ' '
chomp :: String -> String
chomp = strip ' '
What do you think? Is it possible to add such functions to Data.String?

I need convert this string in Char List

I'm learning haskell. I'm reading a string from a text file and need to make this string becomes a list of char.
The input file is this:
Individuo A; TACGATCAAAGCT
Individuo B; AATCGCAT
Individuo C; TAAATCCGATCAAAGAGAGGACTTA
I need convert this string
S1 = "AAACCGGTTAAACCCGGGG" in S1 =
["A","A","A","C","C","G","G","T","T","A","A","A","C","C","C","G","G","G","G"]
or S1 =
['A','A','A','C','C','G','G','T','T','A','A','A','C','C','C','G','G','G','G']
but they are separated by ";"
What should I do?
What can I do?
after getting two lists, I send them to this code:
lcsList :: Eq a => [a] -> [a] -> [a]
lcsList [] _ = []
lcsList _ [] = []
lcsList (x:xs) (y:ys) = if x == y
then x : lcsList xs ys
else
let lcs1 = lcsList (x:xs) ys
lcs2 = lcsList xs (y:ys)
in if (length lcs1) > (length lcs2)
then lcs1
else lcs2
A rough and ready way to split out each of those strings is with something like this - which you can try in ghci
let a = "Individuo A; TACGATCAAAGCT"
tail $ dropWhile (/= ' ') $ dropWhile (/= ';') a
which gives you:
"TACGATCAAAGCT"
And since a String is just a list of Char, this is the same as:
['T', 'A', 'C', 'G', ...
If your file consists of several lines, it is quite simple: you just need to skip everything until you find “;”. If your file consists of just one line, you’ll have to look for sequences’ beginnings and endings separately (hint: sequence ends with space). Write a recursive function to do the task, and use functions takeWhile, dropWhile.
A String is already a list of Char (it is even defined like this: type String = [Char]), so you don’t have to do anything else. If you need a list of Strings, where every String consists of just one char, then use map to wrap every char (once again, every String is a list, so you are allowed to use map on these). To wrap a char, there are three alternatives:
Use lambda function: map (\c -> [c]) s
Use operator section: map (:[]) s
Define a new function: wrap x = [x]
Good luck!

How to convert a list of (Char,Int) to a string with the given number of repeated chars?

How can I convert [(char,Int)] to a String of the Int in the second component gives the number of repetitions of the character in the first component? For example the input [(a,9),(b,10)] should give ["aaaaaaaaa","bbbbbbbbbb"] as output.
Hugs> map (\(c,n) -> replicate n c) [('a',9), ('b',10)]
["aaaaaaaaa","bbbbbbbbbb"]
or
map (uncurry $ flip replicate)
This can be assembled from just a few functions in the Prelude. Since your input is a list of tuples, the return value becomes a list of strings.
repChars :: (Char, Int) -> String
repChars (c,n) = replicate n c
Prelude> map repChars [('a',9),('b',10)]
["aaaaaaaaa","bbbbbbbbbb"]
Or if you want to do it as a point-free one-liner:
repCharList = map (uncurry (flip replicate))
Is this homework? If so, please use the homework tag.
I'm assuming the input is supposed to be [('a', 9), ('b', 10)] since without the 's it would only make sense if a and b were previously defined, which you did not mention.
In that case you can use replicate to create a list which contains a given element a given number of times (note that the string "aaaaaaaaaa" is a list containing the element 'a' 9 times). To do that for every tuple in the list, you can use map on the list. Now you have a list containing the strings for each character. To turn that into a single string separated by commas, you can use intercalate, which takes a separator and a list of lists and returns a single li.
The facetious and horrible answer:
Prelude> let replignore ((_,x):[]) = [replicate x 'b']; replignore ((_,x):xs) = replicate x 'a' : replignore xs
Prelude> replignore [(a,9),(b,10)]
<interactive>:1:13: Not in scope: `a'
<interactive>:1:19: Not in scope: `b'
Prelude> let a = undefined
Prelude> let b = undefined
Prelude> replignore [(a,9),(b,10)]
["aaaaaaaaa","bbbbbbbbbb"]
But it didn't quite fit the specs since it includes the quotation marks in the answer. ;)
My point is, you need quotes around your Char and String literals.

Resources