Check if a string contains a certain character using recursion - haskell

I know how to check if a string contains a certain character like this:
charFound :: Char -> String -> Bool
charFound c s = c `elem` s
Now, how could I have the same approach using recursion?
Also, using Pattern Matching to check if one of the parameters is empty, I'm getting
Parse Error In pattern: ' ' s
charFound:: Char->String->Bool
charFound '' s = error "Something is empty." -- ERROR
charFound c "" = error "Something is empty." -- OK
Am I allowed to use the _ to ignore a parameter with something that's not a list ?
Update Currently code
charFound :: Char->String->Bool
charFound c (x:xs)
| c == x = True
| xs == "" = False
| otherwise = contido c xs
Also
charFound :: Char->String->Bool
charFound _ "" = False -- returns false if I type > charFound 'a' "Leh"
charFound c (x:xs)
| c == x = True
| otherwise = contido c xs

We can keep the same signature, because the function does the same thing.
charFound :: Char -> String -> Bool
When you are performing recursion you always want to make sure you consider your base case, in this case it would be when you are looking for a character in an empty String, which should obviously always return false.
charFound c "" = False
Now you have to consider the other case, where the String is not empty. If the string is not empty, then it is of the form (x:xs), and if x equals our character then we return true, otherwise we check whether c is in xs.
charFound c (x:xs)
| c == x = True
| otherwise = charFound c xs
Alternatively,
charFound c (x:xs) = c == x || charFound c xs
Edit:
To answer your additional question about pattern matching, you are getting that warning because '' is not a character! A character can never be empty, so you don't need to consider that possibility.
Also, you definitely can use _ to match on something that is not a list. You can use _ to match any parameter you like. For example, the base case could have been written as
charFound _ "" = False
Because we don't actually need to know what the value of the character is when the String is empty, so we don't need to give it a name.

Related

Haskell check in list

I have a string which has several words in it, and I have to check if the first character is the same as the previous word last character. I've been told to use the the words built in function.
Here is what I've done:
validGame1 :: [String] -> Bool
validGame1 [] = True
validGame1 [x] = True
validGame1 (a:b:xs)
|last a == head b = validGame1 (b:xs)
|otherwise = False
but i'm getting exceptions when the input should be True
example : validGame "bread door room mad" (this should be True but it throws an exception)
validGame "bread car room mad" (this should be False and it works well)
It seems like you are forgetting to use words. This works for me:
ghci> validGame1 (words "bread door room mad")
True
ghci> validGame1 (words "bread car room mad")
False
If you want to encapsulate that into one function you can write:
validGame1 :: String -> Bool
validGame1 inp = go (words inp) where
go [] = True
go [x] = True
go (a:b:xs)
| last a == head b = go (b:xs)
| otherwise = False
As an addendum, it's possible to solve this problem without ever using words simply with recursion and pattern matching.
check :: [Char] -> Bool
check "" = True
check [_, _] = True
check (a:tl#(' ':b:c))
| a == b = check tl
| otherwise = False
check (_:tl) = check tl
We can consider any one or two character string to meet the specifications laid out.
For three or more characters, if the middle character is a space, if the two characters on either side are the same, we can check the tail of the string. Otherwise we know the string does not pass the check and return False.
If the string is three or more characters, but the middle character is not a space, continue checking the tail of the string.
Note: this does not handle a string where words are separate by multiple spaces.
If we want to handle that scenario, we can add a few patterns to our function.
check :: [Char] -> Bool
check "" = True
check [_, _] = True
check (' ':tl#(' ':b:_)) = check tl
check (a:tl#(' ':' ':_)) = check $ a:' ':(dropWhile (== ' ') tl)
check (a:tl#(' ':b:_))
| a == b = check tl
| otherwise = False
check (_:tl) = check tl

Having trouble with isUpper function in use

Is it OK to write the otherwise part this way? The function should lower the uppercase letters and put the space in front. It keeps giving an error.
functionl s
| s==[] = error "empty"
| otherwise = [ if isUpper c then (" " ++ toLower c) else c | c <-read s::[Char] ]
First, Note that the return type of (" "++ toLower c) is a String ([Char]) if it was done properly - but it isn't. I'll show you below.
But before that, note that in this specific list comprehension, you have else c which is a single Char.
Your return types must match.
This might be a suitable replacement: concat [ if (isUpper c) then (" "++[c]) else [c] | c <-s ]
Your list comprehension is almost right as #Arnon has shown, but you could definitely implement this function more easily using recursion:
-- A descriptive name and a type signature help
-- tell other programmers what this function does
camelCaseToWords :: String -> String
camelCaseToWords [] = []
camelCaseToWords (c:cs)
| isUpper c = ' ' : toLower c : camelCaseToWords cs
| otherwise = c : camelCaseToWords cs
Now, this pattern can be abstracted to use a fold, which is Haskell's equivalent of a basic for-loop:
camelCaseToWords cs = foldr replacer [] cs
where
replacer c xs
| isUpper c = ' ' : toLower c : xs
| otherwise = c : xs
Here each step of the iteration is performed by replacer, which takes the current character c, an accumulated value xs and returns a new value to be used in the next iteration. The fold is seeded with an initial value of [], and then performed over the entire string.

Haskell passing empty Character to a function

I'm working in Haskell in two functions:
Basically I want to get the character before matching a specific character in a given string
This is my code:
before :: Char -> [Char] -> Char
before x str = trackelement x ' ' str
trackelement :: Char -> Char -> [Char] -> Char
trackelement x y (z:zs)
| x == z = y
| otherwise = trackelement x z (zs)
My problem is when I try: before 'l' "luis"
The answer is : ' ' (of course, before 'l' there is nothing), and I would like to be '' or Nothing
I tried passing trackelement x '' str instead of trackelement x ' ' str but I have this error Syntax error on ''str
Could you suggest me something?
The answers shown already are good for getting your code to work, but they don't explain why you get the error you're receiving. The reason why that error was shown is that '' is not valid syntax, since there is no such thing as an "empty character". All characters have value, but Strings can be empty. Remember that type String = [Char], and it's very clear that there can be such a thing as an empty list, but characters always have a value. It's comparable to saying you can have an empty list of Ints, namely [], but you can't have an "empty int", whatever that would mean.
You can use a Maybe:
before :: Char -> [Char] -> Maybe Char
before x str = initialise x str
initialise x (y:xs)
| x == y = Nothing
| otherwise = trackelement x y xs
trackelement :: Char -> Char -> [Char] -> Maybe Char
trackelement x y [] = Nothing
trackelement x y (z:zs)
| x == z = Just y
| otherwise = trackelement x z zs
To take care of the corner case before 'l' "luis", we have to add a new initialiser function. It basically checks if the first character matches the searched one. If it does, we return Nothing, because we checked the first character which obviously does not have a preceding one. Else we just call trackelement and use it's result.
As Zeta mentioned, you can combine the functions, which simplifies everything and takes care of the corner case you are currently experiencing.
before _ [x] = Nothing
before a (x:y:xs)
| a == y = Just x
| otherwise = before a (y:xs)
Just using this function, you noticed you have problems when encountering a word containing more than one letter which is also searched for (before 'a' "amalia" -> Just 'm'). Currently the best solution I know of is again splitting this up into more than one function, which brings us back to the solution at the top.
Match the first two elements instead just head and tail. That way you don't even need trackelement:
before :: Eq a => a -> [a] -> Maybe a
before x (a:b:rest)
| a == x = Nothing
| b == x = Just a
| otherwise = before x (b:rest)
before _ _ = Nothing

Haskell - string function

I need to write function, which is seeking for "Z" in string, and when this function finds it on i index, it appends i+3 Char to table.
Here is my code:
someFun :: String => String -> String -> String
someFun "" (r:rs) = (r:rs)
someFun (a:b:c:d:xs) (r:rs)
| a == "Z" = someFun xs ((r:rs)++d)
| otherwise = someFun (b:c:d:xs) (r:rs)
I got bunch of errors that I don't know how to fix due to my poor experience in Haskell programming.
EDIT:
If input is "(C (N (Z 'p')) (A (K (Z 'p') (Z 'q')) (Z 'r')))"
its output should be: ['p','q','r']
The specification is not entirely clear, but it sounds like you want to collect all the characters which occur three places after a 'Z' in the input, so that from
"BUZZARD BAZOOKA ZOOM"
we get
"RDKM"
Without a clearer presentation of the problem, it is difficult to give precise advice. But I hope I can help you get past some of the small irritations, so that you can engage with the actual logic of the problem.
Let's start with the type. You have
someFun :: String => String -> String -> String
but left of => is the place for properties of type expressions, usually involving variables that could stand for lots of types, such as Eq a (meaning that whatever type a is, we can test equality). String is a type, not a property, so it cannot stand left of =>. Drop it. That gives
someFun :: String -- input
-> String -- accumulating the output (?)
-> String -- output
It is not clear whether you really need an accumulator. Suppose you know the output for
"ZARD BAZOOKA BOOM" -- "DKM", right?
Can you compute the output for
"ZZARD BAZOOKA BOOM" -- "RDKM"
? Just an extra 'R' on the front, right? You're using tail recursion to do the next thing, when it is usually simpler to think about what things should be. If you know what the output is for the tail of the list, then say what the output is for the whole of the list. Why not just map input to output directly, so
someFun :: String -> String
Now, pattern matching, start with the simplest possible pattern
someFun s = undefined
Can you see enough about the input to determine the output? Clearly not. It matters whether the input is empty or has a first character. Split into two cases.
someFun "" = undefined
someFun (c : s) = undefined -- c is the first Char, s is the rest of the String
It also matters whether the first character is 'Z' or not. Be careful to use single quotes for Char and double quotes for String: they are different types.
someFun "" = undefined
someFun ('Z' : s) = undefined -- the first Char is Z
someFun (c : s) = undefined
In the case wit 'Z', you also want to make sure that s has at least three characters, and we care about the third, so
someFun "" = undefined -- input empty
someFun ('Z' : s#(_ : _ : d : _)) = undefined -- first is 'Z' and d is 3 later
someFun (c : s) = undefined -- input nonempty
The # is an "as pattern", allowing me to name the whole tail s and also check that it matches (_ : _ : d : _), grabbing the third character after the 'Z'.
So far, I've given no thought to the output, just what I need to see about the input. Let's figure out what the output must be. In the first case, empty input gives empty output
someFun "" = ""
someFun ('Z' : s#(_ : _ : d : _)) = undefined -- first is 'Z' and d is 3 later
someFun (c : s) = undefined -- input nonempty
and in the other two cases, we can assume that someFun s already tells us the output for the tail of the list, so we just need to figure out how to finish the output for the whole list. In the last line, the output for the tail is just what we want.
someFun "" = ""
someFun ('Z' : s#(_ : _ : d : _)) = undefined -- first is 'Z' and d is 3 later
someFun (c : s) = someFun s
But in the case where we've found that d is three places after the initial 'Z', we need to make sure d is at the start of the output.
someFun "" = ""
someFun ('Z' : s#(_ : _ : d : _)) = d : someFun s
someFun (c : s) = someFun s
Just checking:
*Main> someFun "BUZZARD BAZOOKA ZOOM"
"RDKM"
The key idea is to figure out how to express the output for the whole input in terms of the output for its pieces: what it is, not what to do. Here, you can assume that the output for the tail, s is correctly computed, so you just need to figure out whether you have anything extra to return.
It's not really clear what you're trying to do but this compiles:
someFun :: String -> String -> String
someFun "" (r:rs) = (r:rs)
someFun (a:b:c:d:xs) (r:rs)
| a == 'Z' = someFun xs ((r:rs)++[d])
| otherwise = someFun (b:c:d:xs) (r:rs)
The String => is for typeclass constraints, which you don't need.
d is a Char while (++) is defined on lists (of Chars in this case).
Your function has incomplete pattern matches, so you could also define those, which will simplify the existing cases:
someFun :: String -> String -> String
someFun _ [] = error "Empty string"
someFun "" s = s
someFun ('Z':b:c:d:xs) s = someFun xs (s++[d])
someFun (_:b:c:d:xs) s = someFun (b:c:d:xs) s
someFun _ _ = error "String was not in the expected format"
To display it on the screen you can use putStrLn or print:
displaySomeFun :: String -> String -> IO ()
displaySomeFun s1 s2 = putStrLn (someFun s1 s2)
Lee showed how you get it to compile.
There are still some things to say about:
You have to provide more pattern-cases, You get an error for example if you try to run someFun "" "", or someFun "A" "ABCD"
First improvement: Change (r:rs) to rs, you never use r, so you can change it to a more general case (that will fix the error on someFun "" "").
The other thing is, that you don't pattern match on lists with one, two, or tree elements.
You could add someFun _ rs = rs, so that in those cases nothing happens.
Read about head and tail.It is easier with them.And end the cycle when the length of your first list is less than 4.
someFun [] rs = rs
someFun xs rs
| (length xs) < 4 = rs
| (head xs) == 'Z' = someFun (tail xs) (rs ++ [head (tail (tail (tail xs)))])
| otherwise = someFun (tail xs) rs
You can take advantage of how failing pattern-matches work in list comprehensions and the Data.List.tails function:
import Data.List (tails)
someFun :: String -> String
someFun s = [x | 'Z':_:_:x:_ <- tails s]
The tails function gives you all tails of a list (remember that a String ist just a list of Char), e.g.:
λ: tails "Overflow"
["Overflow","verflow","erflow","rflow","flow","low","ow","w",""]
The pattern ('Z':_:_:x:_) matches any string which starts with a Z and is at least four characters in size. For each pattern match, the character which is three positions after Z is extracted.
The magical part about it is that when the pattern fails (e.g. for tails which don't start with a Z or which are too short), the element is skipped silently and doesn't contribute to the result - exactly what you seem to request.

Detecting Pig-Latin In Haskell

I've tried to write a function to do this but can't get GHCI to understand my code. I'm coming from an OOP background so functional programming is completely new territory for me.
checkPigLatin :: String -> String
checkPigLatin sentence (x:xs)
| check == "true" = "This is Pig Latin"
| otherwise = "Not Pig Latin"
where check = if (x `elem` "aeiouAEIOU", '-' `elem` xs, snd(break('a'==) xs) == 'a', snd(break('a'==) xs) == 'y') then "true"
Several issues here:
The type of your function is String -> String, so it should only have one argument, while your definition has two arguments, sentence and (x:xs).
Don't use strings like "true" and "false". Use booleans. That's what they're for.
The condition of an if must be a boolean. If you want several conditions to hold, use (&&) or and to combine them.
An if-expression must have both a then and an else. You can think of if x then y else z like the ternary x ? y : z operator in some other languages.
'a' and 'y' have type Char, so you can't compare them against strings with ==. Compare with "a" and "y" instead.
However, there is no point in writing if something then True else False. Instead, just use the boolean expression directly.
checkPigLatin :: String -> String
checkPigLatin (x:xs)
| check = "This is Pig Latin"
| otherwise = "Not Pig Latin"
where check = and [ x `elem` "aeiouAEIOU"
, '-' `elem` xs
, snd (break ('a'==) xs) == "a"
, snd (break ('a'==) xs) == "y"
]
There are a few things wrong with your code, but they're all minor.
When you say checkPigLatin sentence (x:xs), you are saying that your function takes two arguments: sentence, and (x:xs). What you mean to say is just (x:xs).
There's no need to return "true", which is a String, when you can return True :: Bool. Bool is already the type that the expression inside the if returns. This means you don't need the if statement at all.
In the predicate in the parentheses, you use , as the logical AND, but in Haskell it's &&
The result of break is a string, so write "a" for its second argument, not 'a'
Lastly - and this is about pig latin, not Haskell - I'm not sure that failing (snd(break('a'==) xs) == "a") is going to guarantee something is not pig latin
Hope this helps, and welcome!
Edit:
Here's the updated code, if you'd like it:
checkPigLatin :: String -> String
checkPigLatin (x:xs)
| check = "This is Pig Latin"
| otherwise = "Not Pig Latin"
where check = (x `elem` "aeiouAEIOU") &&
('-' `elem` xs) &&
(snd(break('a'==) xs) == "a") &&
(snd(break('a'==) xs) == "y")
Not quite sure what's going on in that string-checks, but maybe this is what you need.
checkPigLatin :: String -> String
checkPigLatin [] = "Empty string"
checkPigLatin (x:xs)
| check = "This is Pig Latin"
| otherwise = "Not Pig Latin"
where check = and [ x `elem` "aeiouAEIOU"
, '-' `elem` xs
, snd ( break ('a' == ) xs ) == "a"
, snd (break ('a' == ) xs) == "y"
]
And
pisya> checkPigLatin "checkPigLatin"
"Not Pig Latin"
it :: String

Resources