Return Bool if a specific value repeats - haskell

I'm currently doing a project for school about email identification but there is a certain part of the code that I have been stuck for quite a while, I've been trying to figure out how I could return Bool if a certain value would repeat.
This is my current code:
The idea is to build a function that searches if a certain value is repeated
repeated :: [Char] -> Bool
repeated [] = False
repeated [_] = False
repeated (x:xs) = if elem x xs then True else repeated xs
At this part of the code I don't know how to specify the value that I want to return Bool if it repeats
special :: [String] -> [String]
special x = filter (elem ['.','_']) (map repeated x)
the expected output was this:
special "penuts.."
True

Now that you have a solution, and so I don't feel I'm ruining a good learning experience, here are some additional implementation ideas that you might enjoy.
If you want to check a single character's repeated-ness status, you could ask for just the copies of that character, and then check whether there's two (or more) of them.
repeats :: Eq a => a -> [a] -> Bool
repeats a as = case filter (a==) as of
_:_:_ -> True
_ -> False
However, this might be less efficient if you have many repeats queries you want to make. If that's so, you may want to preprocess the list, paying some up-front cost to make future queries faster. One way would be to count each of the elements.
import qualified Data.Map as M
count :: Ord a => [a] -> M.Map a Int
count as = M.fromListWith (+) [(a, 1) | a <- as]
Given counts, it's easy to check whether a given character repeats.
repeats' :: Ord a => a -> M.Map a Int -> Bool
repeats' a as = M.findWithDefault 0 a as >= 2
For example, to check multiple characters for repetition at once, you might write:
multirepeats :: Ord a => [a] -> [a] -> Bool
multirepeats needle haystack = or [repeats' a as | a <- needle] where
as = count haystack
Giving the result of the call to count a name in a where block means it will be computed just once in each call to multirepeats (at least, when using GHC).
If you wanted to check whether there is any repeating character, you could reuse count like this:
anyRepeats :: Ord a => [a] -> Bool
anyRepeats = any (>=2) . count
Or, you could do this directly with list-based operations if you sort first:
import Data.List
anyRepeats' :: Ord a => [a] -> Bool
anyRepeats' as = not $ null [() | _:_:_ <- group (sort as)]

After reviewing my function, i came across with the solution
element :: Eq t => t -> [t] -> Bool
element _[] = False
element x (y : ys) = if x == y then elem x ys else element x ys
if the specific value repeats, the boolean value output should be True:
element '.'"ban.nan."
True

i also got my desire solution output:
repeatedLocal :: [Char] -> Bool
repeatedLocal [] = False
repeatedLocal [_] = False
repeatedLocal (x:xs) = if elem x ['.', '_'] then True else repeated xs

Related

Catch empty list exeption in Haskell (head)

I'm writing a function that gets the index of the first even number from a list. The list I get may or may not contain even numbers, and I'd like to return -1 if there are no even numbers in the list. The list can be infinite.
I wrote this
posicPrimerPar'' :: [Int] -> Int
posicPrimerPar'' a = fromJust (elemIndex (head (filter (even) a)) a)
I could do something like:
posicPrimerPar' :: [Int] -> Int
posicPrimerPar' a = case length evens of
0 -> -1;
n -> fromJust elemIndex (head evens) a
where evens = filter (even) a
But as you can see, this is not the most efficient way of doing it. A list [1..100000] contains a lot of even numbers, and I just need the first one. I need Haskell's laziness, so I need to ask for the head right there, but head throws an empty list exception when the list is empty (i.e. there are no even numbers in the list). I cannot find the Haskell equivalent of Python's try: ... except: .... All I could find regarding exceptions were IO related. What I need is except Prelude.head = -1 or something like that.
Haskell is lazy, so evens will not be fully evaluated. The problematic part is the length evens which is not necessary. You can check with null :: Foldable f => f a -> Bool, or with pattern matching. For example:
import Data.List(findIndex)
posicPrimerPar' :: [Int] -> Maybe Int
posicPrimerPar' [] = Nothing
posicPrimerPar' xs = findIndex even xs
for findIndex :: (a -> Bool) -> [a] -> Maybe Int, you however do not need to take into account the empty list, since it already considers this.
or we can return -1 in case there is no such item:
import Data.List(findIndex)
import Data.Maybe(fromMaybe)
posicPrimerPar' :: [Int] -> Int
posicPrimerPar' = fromMaybe (-1) . findIndex even

Haskell Check if only element satisfies a given condition

I am working on a assignment that checks if there is only a single element that satisfies a given condition, I've thought about passing map to get a list of Boolean values and then counting if it has value 1 if it does I return True if not then I return False.
single :: (a -> Bool) -> [a] -> Bool
single p [] = False
single p a = map p a
let c = single p a
single count True c = if k == 1
then True
else False
Which I have count that is:
count :: (Num a, Eq b) => b -> [b] -> a
count _ [] = 0
count x list = sum $ map (const 1) $ filter (== x) list
Your solution contains some errors. For example the second parameter of single is a list, so single count True c makes no sense. You can work with:
single :: (a -> Bool) -> [a] -> Bool
single p a = count True (map p a) == 1
but is not very efficient. filter p a will produce a list with the same length as filter (== True) (map p a), and does not require first mapping and then filtering. Furthermore by counting the number of items that satisfy the condition, you will enumerate over the entire list, even if you already found two items that match, and you thus know that it can no longer contain exactly one item that matches.
You can work with filter and pattern match on an list with exactly one item, and let this return True, for the two other cases (the empty list, and a list with two or more items), we return False, so:
single :: (a -> Bool) -> [a] -> Bool
single p a = case filter p a of
[_] -> True
_ -> False
This will prevent enumerating over the entire list if it can find two items that satisfy the given condition.

Check a string if a letter is used only once Haskell

How do i check that each letter is used only once in the string inputed by the user and return boolean if true
For
appearsOnlyOnce :: String -> Bool
an inefficient (quadratic) way to do so is by
appearsOnlyOnce [] = True
appearsOnlyOnce (x:xs)
| x `elem` xs = False
| otherwise = appearsOnlyOnce xs
A more efficient, but more complicated way, would be to sort and check adjacent elements.
Here's an easy way that's not too inefficient:
import Data.Containers.ListUtils
noDuplicates :: Ord a => [a] -> Bool
noDuplicates xs = xs == nubOrd xs
nubOrd removes duplicates, keeping the other elements in order. If there's a duplicate, then the nubbed list will differ from the original.

Checking for empty list in Haskell: Is (length list == 0) or (list == []) more efficient?

Say I want to check if a list is empty in a guard in Haskell there are two options:
length list == 0
list == []
Which of these two logical tests are more efficient? I'm inclined to say the empty list test because relies on more basic constructs rather than the prelude function length but I'm not sure.
length list == 0 needs to traverse the whole list to get its length, which means it is O(n). list == [] yields an Eq constraint on the element type. null list runs in constant time and has no typeclass constraints.
However, there is a neat trick to do something like length list == 0 which has the advantage that it generalizes nicely to length list1 == length list2 without going through the longer list: you can use genericLength with a sufficiently lazy representation of natural numbers so that comparison will only force traversing the shorter of the lists.
One example is to use the Natural type:
import Data.Number.Natural
import Data.List (genericLength)
nats :: [Int]
nats = iterate succ 0
areThereTenNats :: Bool
areThereTenNats = genericLength nats >= (10 :: Natural)
You can check if your list is empty in constant time with null list, which returns a boolean.
Prelude> null []
True
Prelude> null [1]
False
Prelude> null ""
True
Prelude> null "Test"
False
As others have indicated, the best way to check if a list is empty (and nothing more) is to use
null :: Foldable f => f a -> Bool
which can be used at type
null :: [a] -> Bool
If you want to check if a list is empty because you want to look at its elements otherwise, you generally should be using pattern matching instead:
f [] = something
f (x : xs) = something using x and/or xs
If you want to compare the lengths of two lists (and no more), the best way is usually something like
compareLength :: [a] -> [b] -> Ordering
compareLength [] [] = EQ
compareLength [] (_ : _) = LT
compareLength (_ : _) [] = GT
compareLength (_ : xs) (_ : ys) =
compareLength xs ys
The best way to check how the length of a list compares to a certain number is
compareToLength :: Foldable f
=> f a -> Int -> Ordering
compareToLength = foldr go (compare 0) where
go _ r n | n <= 0 = GT
| otherwise = r $! n - 1

Creating a function using subset language Core Haskell to remove duplicate items in a list

The language I'm using is a subset of Haskell called Core Haskell which does not allow the use of the built-in functions of Haskell. For example, if I were to create a function which counts the number of times that the item x appears in the list xs, then I would write:
count = \x ->
\xs -> if null xs
then 0
else if x == head xs
then 1 + count x(tail xs)
else count x(tail xs)
I'm trying to create a function which outputs a list xs with its duplicate values removed. E.g. remdups (7:7:7:4:5:7:4:4:[]) => (7:4:5:[])
can anyone offer any advice?
Thanks!
I'm guessing that you're a student, and this is a homework problem, so I'll give you part of the answer and let you finish it. In order to write remdups, it would be useful to have a function that tells us if a list contains an element. We can do that using recursion. When using recursion, start by asking yourself what the "base case", or simplest possible case is. Well, when the list is empty, then obviously the answer is False (no matter what the character is). So now, what if the list isn't empty? We can check if the first character in the list is a match. If it is, then we know that the answer is True. Otherwise, we need to check the rest of the list -- which we do by calling the function again.
elem _ [] = False
elem x (y:ys) = if x==y
then True
else elem x ys
The underscore (_) simply means "I'm not going to use this variable, so I won't even bother to give it a name." That can be written more succinctly as:
elem _ [] = False
elem x (y:ys) = x==y || elem x ys
Writing remdups is a little tricky, but I suspect your teacher gave you some hints. One way to approach it is to imagine we're partway through processing the list. We have part of the list that hasn't been processed yet, and part of the list that has been processed (and doesn't contain any duplicates). Suppose we had a function called remdupHelper, which takes those two arguments, called remaining and finished. It would look at the first character in remaining, and return a different result depending on whether or not that character is in finished. (That result could call remdupHelper recursively). Can you write remdupHelper?
remdupHelper = ???
Once you have remdupHelper, you're ready to write remdups. It just invokes remdupHelper in the initial condition, where none of the list has been processed yet:
remdups l = remdupHelper l [] -- '
This works with Ints:
removeDuplicates :: [Int] -> [Int]
removeDuplicates = foldr insertIfNotMember []
where
insertIfNotMember item list = if (notMember item list)
then item : list
else list
notMember :: Int -> [Int] -> Bool
notMember item [] = True
notMember item (x:xs)
| item == x = False
| otherwise = notMember item xs
How it works should be obvious. The only "tricky" part is that the type of foldr is:
(a -> b -> b) -> b -> [a] -> b
but in this case b unifies with [a], so it becomes:
(a -> [a] -> [a]) -> [a] -> [a] -> [a]
and therefore, you can pass the function insertIfNotMember, which is of type:
Int -> [Int] -> [Int] -- a unifies with Int

Resources