Find and replace in Haskell - haskell

I want to input a list of 2 element lists of characters (just letters) where the first element is a letter in a String (the second argument for findAndReplace) and the second is what I want it changed to. Is there already a function in Haskell that does a similar thing? Because this would help greatly!

It sounds more like you might want to use a list of tuples instead of a list of lists for your first input, since you specify a fixed length. Tuples are fixed-length collections that can have mixed types, while lists are arbitrary-length collections of a single type:
myTuple = ('a', 'b') :: (Char, Char)
myTriple = ('a', 'b', 'c') :: (Char, Char, Char)
myList = ['a'..'z'] :: [Char]
Notice how I have to specify the type of each field of the tuples. Also, (Char, Char) is not the same type as (Char, Char, Char), they are not compatible.
So, with tuples, you can have your type signature for replace as:
replace :: [(Char, Char)] -> String -> String
And now this specifies with the type signature that it has to be a list of pairs of characters to find and replace, you won't have to deal with bad input, like if someone only gave a character to search for but not one to replace it with.
We now are passing in what is commonly referred to as an association list, and Haskell even has some built in functions for dealing with them in Data.List and Data.Map. However, for this exercise I don't think we'll need it.
Right now you're wanting to solve this problem using a list of pairs, but it'd be easier if we solved it using just one pair:
replace1 :: (Char, Char) -> String -> String
replace1 (findChr, replaceChr) text = ?
Now, you want to check each character of text and if it's equal to findChr, you want to replace it with replaceChr, otherwise leave it alone.
replace1 (findChr, replaceChr) text = map (\c -> ...) text
I'll let you fill in the details (hint: if-then-else).
Then, you can use this to build your replace function using the simpler replace1 function. This should get you started, and if you still can't figure it out after a day or two, comment below and I'll give you another hint.

Related

How to convert a string to an array containing each character in Haskell?

I was looking at this post here:
Haskell get character array from string?
I see it says that in haskell strings are essentially arrays containing each letter, but I was wondering; how would I turn the format from the string to an array of individual components, for example:
["ABCD","EFGH"]
to
[["A","B","C","D"],["E","F","G","H"]]
I'd like to know a method without using any external imports.
You can wrap each element in a singleton list, so:
map (map pure) ["ABCD", "EFGH"] :: [[String]]
this then produces:
Prelude> map (map pure) ["ABCD", "EFGH"] :: [[String]]
[["A","B","C","D"],["E","F","G","H"]]
That being said, a String is simply a list of Chars, indeed:
type String = [Char]
so if you just want to work with a list of Chars, you can simply work with the string directly. By converting it to a list of list of Strings, we know that all these strings contain one Char, but that is no longer guaranteed by the type.

Haskell: Couldn't match type ‘Char’ with ‘[Char]’

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').

converting a list of string into a list of tuples in Haskell

I have a list of strings:
[" ix = index"," ctr = counter"," tbl = table"]
and I want to create a tuple from it like:
[("ix","index"),("ctr","counter"),("tbl","table")]
I even tried:
genTuple [] = []
genTuples (a:as)= do
i<-splitOn '=' a
genTuples as
return i
Any help would be appriciated
Thank you.
Haskell's type system is really expressive, so I suggest to think about the problem in terms of types. The advantage of this is that you can solve the problem 'top-down' and the whole program can be typechecked as you go, so you can catch all kinds of errors early on. The general approach is to incrementally divide the problem into smaller functions, each of which remaining undefined initially but with some plausible type.
What you want is a function (let's call it convert) which take a list of strings and generates a list of tuples, i.e.
convert :: [String] -> [(String, String)]
convert = undefined
It's clear that each string in the input list will need to be parsed into a 2-tuple of strings. However, it's possible that the parsing can fail - the sheer type String makes no guarantees that your input string is well formed. So your parse function maybe returns a tuple. We get:
parse :: String -> Maybe (String, String)
parse = undefined
We can immediately plug this into our convert function using mapMaybe:
convert :: [String] -> [(String, String)]
convert list = mapMaybe parse list
So far, so good - but parse is literally still undefined. Let's say that it should first verify that the input string is 'valid', and if it is - it splits it. So we'll need
valid :: String -> Bool
valid = undefined
split :: String -> (String, String)
split = undefined
Now we can define parse:
parse :: String -> Maybe (String, String)
parse s | valid s = Just (split s)
| otherwise = Nothing
What makes a string valid? Let's say it has to contain a = sign:
valid :: String -> Bool
valid s = '=' `elem` s
For splitting, we'll take all the characters up to the first = for the first tuple element, and the rest for the second. However, you probably want to trim leading/trailing whitespace as well, so we'll need another function. For now, let's make it a no-op
trim :: String -> String
trim = id
Using this, we can finally define
split :: String -> (String, String)
split s = (trim a, trim (tail b))
where
(a, b) = span (/= '=') s
Note that we can safely call tail here because we know that b is never empty because there's always a separator (that's what valid verified). Type-wise, it would've been nice to express this guarantee using a "non-empty string" but that may be a bit overengineered. :-)
Now, there are a lot of solutions to the problem, this is just one example (and there are ways to shorten the code using eta reduction or existing libraries). The main point I'm trying to get across is that Haskell's type system allows you to approach the problem in a way which is directed by types, which means the compiler helps you fleshing out a solution from the very beginning.
You can do it like this:
import Control.Monda
import Data.List
import Data.List.Split
map ((\[a,b] -> (a,b)) . splitOn "=" . filter (/=' ')) [" ix = index"," ctr = counter"," tbl = table"]

Postal address validation using haskell

i am extremely new to Haskell..
i want to validate postal address using Haskell.
29b, roadname, cityname, postalcode, country
i want to validate the following
1)first section (29b)must have at least a number at start.
2)roadname, cityname, country are characters.
3)postal code is of 6 digits either a character or a integer.
4) each of them are separated by comma(,)
i started tried this , but i was unable to do it.
validtion :: String -> Bool
validtion [] = []
validtion (x:xs)
|(isInt :xs) = validtion xs
|(',':xs) = validtion xs
validtion (x:xs)= x: validtion xs
can anyone help me to solve this problem.
Since this is clearly a homework and you haven't paid any attempt at reading Haskell docs, I'll only hand-wave some hints and clues here and will fill the answer at the end of the month.
First thing, no value (function in your case) in Haskell can start with a capital letter. So Validtion (don't know why you constantly miss the a) is invalid identifier.
Then, you cannot have both = and guards, not to mention that the guards must be aligned on the same column.
Third, (isInt : xs) means a list with at least one element, that first element can be referred to by isInt and all other elements by xs. Similarly, ',':xs means a string which starts with ,.
Now, how to solve it: you need a function String -> Bool but since String has several parts you need to split it in words and remove the ,s. Search on Hoogle for String -> [String] and String -> String -> String to find out what functions to use.
Now, having a list [String] you need to validate each element of that list in part. Import Data.Char and use functions from there together with map.
Finally, from a list [Bool] to get a Bool you go again to Hoogle and search for [Bool] -> Bool.
PS: Have a look at LYAH and RWH. They are both good resources for learning and freely available on the internet.

How to access nth element in a Haskell tuple

I have this:
get3th (_,_,a,_,_,_) = a
which works fine in GHCI but I want to compile it with GHC and it gives error. If I want to write a function to get the nth element of a tuple and be able to run in GHC what should I do?
my all program is like below, what should I do with that?
get3th (_,_,a,_,_,_) = a
main = do
mytuple <- getLine
print $ get3th mytuple
Your problem is that getLine gives you a String, but you want a tuple of some kind. You can fix your problem by converting the String to a tuple – for example by using the built-in read function. The third line here tries to parse the String into a six-tuple of Ints.
main = do
mystring <- getLine
let mytuple = read mystring :: (Int, Int, Int, Int, Int, Int)
print $ get3th mytuple
Note however that while this is useful for learning about types and such, you should never write this kind of code in practise. There are at least two warning signs:
You have a tuple with more than three or so elements. Such a tuple is very rarely needed and can often be replaced by a list, a vector or a custom data type. Tuples are rarely used more than temporarily to bring two kinds of data into one value. If you start using tuples often, think about whether or not you can create your own data type instead.
Using read to read a structure is not a good idea. read will explode your program with a terrible error message at any tiny little mistake, and that's usually not what you want. If you need to parse structures, it's a good idea to use a real parser. read can be enough for simple integers and such, but no more than that.
The type of getLine is IO String, so your program won't type check because you are supplying a String instead of a tuple.
Your program will work if proper parameter is supplied, i.e:
main = do
print $ get3th (1, 2, 3, 4, 5, 6)
It seems to me that your confusion is between tuples and lists. That is an understandable confusion when you first meet Haskell as many other languages only have one similar construct. Tuples use round parens: (1,2). A tuple with n values in it is a type, and each value can be a different type which results in a different tuple type. So (Int, Int) is a different type from (Int, Float), both are two tuples. There are some functions in the prelude which are polymorphic over two tuples, ie fst :: (a,b) -> a which takes the first element. fst is easy to define using pattern matching like your own function:
fst (a,b) = a
Note that fst (1,2) evaluates to 1, but fst (1,2,3) is ill-typed and won't compile.
Now, lists on the other hand, can be of any length, including zero, and still be the same type; but each element must be of the same type. Lists use square brackets: [1,2,3]. The type for a list with elements of type a is written [a]. Lists are constructed from appending values onto the empty list [], so a list with one element can be typed [a], but this is syntactic sugar for a:[], where : is the cons operator which appends a value to the head of the list. Like tuples can be pattern matched, you can use the empty list and the cons operator to pattern match:
head :: [a] -> a
head (x:xs) = x
The pattern match means x is of type a and xs is of type [a], and it is the former we want for head. (This is a prelude function and there is an analogous function tail.)
Note that head is a partial function as we cannot define what it does in the case of the empty list. Calling it on an empty list will result in a runtime error as you can check for yourself in GHCi. A safer option is to use the Maybe type.
safeHead :: [a] -> Maybe a
safeHead (x:xs) = Just x
safeHead [] = Nothing
String in Haskell is simply a synonym for [Char]. So all of these list functions can be used on strings, and getLine returns a String.
Now, in your case you want the 3rd element. There are a couple of ways you could do this, you could call tail a few times then call head, or you could pattern match like (a:b:c:xs). But there is another utility function in the prelude, (!!) which gets the nth element. (Writing this function is a very good beginner exercise). So your program can be written
main = do
myString <- getLine
print $ myString !! 2 --zero indexed
Testing gives
Prelude> main
test
's'
So remember, tuples us ()and are strictly of a given length, but can have members of different types; whereas lists use '[]', can be any length, but each element must be the same type. And Strings are really lists of characters.
EDIT
As an aside, I thought I'd mention that there is a neater way of writing this main function if you are interested.
main = getLine >>= print . (!!3)

Resources