Checking for all lowercase & Combining a Word with a List - Haskell - haskell

I am having some trouble writing 2 separate functions. One of which "isWord s" is to take in a word and return "true" if all characters of the word are lowercase, otherwise return "false". Below is an example:
isWord "foo" = True; isWord "fo3o" = False
It must use this definition:
isWord :: String -> Bool
isWord s =
The other function "prefixWords str strs" which takes a word and a list of words and combines the two in a list with a ":" between each word. Shown below as an example:
prefixWords "word:" ["aa", "a3", "foo"] = ["word:aa", "word:foo"]
It must use this definition:
prefixWords :: String -> [String] -> [String]
prefixWords str strs =
Any help is greatly appreciated as I am brand new to Haskell and don't have any idea of where to start. Thanks!

Since this is clearly homework, I won't give you the answers, just a large nudge.
First off, String is just a synonym for [Char].
These functions may be helpful:
(++) :: [a] -> [a] -> [a]
This will concatenate two lists or strings.
import Data.Char
isLower :: Char -> Bool
This will test if a Char is lowercase or not
all :: (a -> Bool) -> [a] -> Bool
This will test whether or not all of a lists elements satisfy a predicate.
map :: (a -> b) -> [a] -> [b]
This applies a function to all elements of a list.
For your function isWord, you need to check that all of a strings elements are/isLower.
For your function prefixWords, every element is concatenated with a given string.

Related

Using data constructor as a function parameter

I am making my way through "Haskell Programming..." and, in Chapter 10, have been working with a toy database. The database is defined as:
data DatabaseItem = DBString String
| DBNumber Integer
| DBDate UTCTime
deriving (Eq, Ord, Show)
and, given a database of the form [databaseItem], I am asked to write a function
dbNumberFilter :: [DatabaseItem] -> [Integer]
that takes a list of DatabaseItems, filters them for DBNumbers, and returns a list the of Integer values stored in them.
I solved that with:
dbNumberFilter db = foldr selectDBNumber [] db
where
selectDBNumber (DBNumber a) b = a : b
selectDBNumber _ b = b
Obviously, I can write an almost identical to extract Strings or UTCTTimes, but I am wondering if there is a way to create a generic filter that can extract a list of Integers, Strings, by passing the filter a chosen data constructor. Something like:
dbGenericFilter :: (a -> DataBaseItem) -> [DatabaseItem] -> [a]
dbGenericFilter DBICon db = foldr selectDBDate [] db
where
selectDBDate (DBICon a) b = a : b
selectDBDate _ b = b
where by passing DBString, DBNumber, or DBDate in the DBICon parameter, will return a list of Strings, Integers, or UTCTimes respectively.
I can't get the above, or any variation of it that I can think of, to work. But is there a way of achieving this effect?
You can't write a function so generic that it just takes a constructor as its first argument and then does what you want. Pattern matches are not first class in Haskell - you can't pass them around as arguments. But there are things you could do to write this more simply.
One approach that isn't really any more generic, but is certainly shorter, is to make use of the fact that a failed pattern match in a list comprehension skips the item:
dbNumberFilter db = [n | DBNumber n <- db]
If you prefer to write something generic, such that dbNUmberFilter = genericFilter x for some x, you can extract the concept of "try to match a DBNumber" into a function:
import Data.Maybe (mapMaybe)
genericFilter :: (DatabaseItem -> Maybe a) -> [DatabaseItem] -> [a]
genericFilter = mapMaybe
dbNumberFilter = genericFilter getNumber
where getNumber (DBNumber n) = Just n
getNumber _ = Nothing
Another somewhat relevant generic thing you could do would be to define the catamorphism for your type, which is a way of abstracting all possible pattern matches for your type into a single function:
dbCata :: (String -> a)
-> (Integer -> a)
-> (UTCTime -> a)
-> DatabaseItem -> a
dbCata s i t (DBString x) = s x
dbCata s i t (DBNumber x) = i x
dbCata s i t (DBDate x) = t x
Then you can write dbNumberFilter with three function arguments instead of a pattern match:
dbNumberFilter :: [DatabaseItem] -> [Integer]
dbNumberFilter = (>>= dbCata mempty pure mempty)

Match type error when counting palindromes in a list in Haskell

I'm getting a match type [Char] with String -> Bool error:
isPalindrome :: String -> Bool
isPalindrome w = w == reverse w
countPalindromes :: [String] -> Int
countPalindromes ss = length (filter (== isPalindrome) ss)
countPalindromes uses isPalindrome to check if a string is a palindrome.
I now have a different issue than in my first question about this palindrome count task. The first issue was solved, and I was instructed to open a new question to solve the new issue. Which is why this is a different question.
isPalindrome :: String -> Bool, which is to say that it expects a string, then gives you a boolean to say whether or not that string is a palindrome.
(==) :: Eq a => a -> a -> Bool, which is to say that it expects two values of typeclass Eq (in other words: anything equatable) and tells you whether or not they are equal.
Pair those together and you get (== isPalindrome) :: (String -> Bool) -> Bool*. You've handed (==) a String -> Bool value, so it's expecting one more and will tell you if the two are equal. That's not quite what you want, though. You're not comparing two functions....
In fact, you're not comparing any two things at all. You only want to see which values passed to countPalindromes return True when called by isPalindrome. That's what filter is for!
filter :: (a -> Bool) -> [a] -> [a]
It's looking for an a -> Bool to pass as the first argument. This is the function that will be deciding what makes it through the filter and what doesn't, and in this case you want to use some derivation of isPalindrome. Looking again at isPalindrome in this context we see:
isPalindrome :: String -> Bool
that looks an awful lot like an a -> Bool function! Let's try substituting all the as in filter's type signature with String.
filter :: (String -> Bool) -> [String] -> [String]
That looks like it's exactly what you're wanting! Try, then, using filter isPalindrome instead of filter (== isPalindrome).
* nitpick: functions (more generally: values of type (-> r)) are not members of the Eq typeclass so you'd actually get an error saying that you can't tell if a String -> Bool is equal to another String -> Bool. It's not relevant to the problem at-hand, though, so I'm pretending that's not an issue and burying this explanation down here.

what does ((Ord, Ord) -> Bool) -> [String] -> String mean in haskell

I changed this question to make it more clear. shortestStringHelper has type (Int -> Int -> Bool) -> [String] -> String. Note the String may appear as [Char] instead depending on how Haskell feels at the time. This function will look a lot like shortestString and shortestString' but it is more general because it takes a function as an argument (Int -> Int -> Bool). Note: Depending on how you write it, you may get (Int -> Int -> Bool) -> [[a]] -> [a], which is also ok.
I know how to write the find the shortest string
shortestString :: [String] -> String
shortestString lst = if null lst then "" else foldl (\shortest x -> if length x < length shortest then x else shortest) (head lst) lst
shortestString' :: [String] -> String
shortestString' lst = if null lst then "" else foldl (\shortest x -> if length x <= length shortest then x else shortest) (head lst) lst
and they work, but I am not sure if I understand this question, and I don't know what does ((Ord, Ord) -> Bool) means.
Ord means something incompatible with that in the Prelude, but ordinarily the type signature you give would be a function with two arguments.
The first argument has type (Ord, Ord) -> Bool, a function that takes a pair of Ord and returns a Bool. In context, this might be intended as a generalized comparison function, such as one that compares the lengths of two strings expressed as whatever an Ord is here. This is unusual, because you would expect something like that to be written like isShorter :: String -> String -> Bool, or maybe isShorter :: [a] -> [a] -> Bool.
The second argument has type [String], a list of String objects. The function returns a single String.
However, you haven’t given us enough information to understand what’s going on in this specific assignment.
Edit: You’ve updated your question so that the type of the first argument is (Int, Int) -> Bool rather than (Ord, Ord) -> Bool, which makes more sense. This might be a way to wrap a comparison on two arguments, such as the lengths of two strings, for a higher-order function that expects one argument.

I want to define a function ‘wordsLength’ that will calculate the length of the words in a given sentence

Sample Input – wordsLength “This is Arya”, Sample output – [4,2,4]
I can get the length for a list of string but not for the string itself.
This is the function you have:
length :: [a] -> Int
What you would like to do is write lengths which preserves the structure of the input list and applies length to each one of its elements.
lengths :: [[a]] -> [Int]
Now, look at the type of map, can you see how to combine length and map to get lengths?
map :: (a -> b) -> [a] -> [b]
length <$> words "This is Arya"

Check if a string contains a certain character

I need to check if my string contain a specific character.
I tried this:
charFound :: Char -> String -> Bool
charFound c s = filter(\x -> x == c) s
But it gives me:
Couldn't match expected type Bool with actual type [Char]
I know that filter:
returns a list constructed from members of a list (the second argument) fulfilling a condition given by the first argument.
How could I reach the goal and return a bool instead of a list?
For your purpose, you could use the function elem :: Eq a => a -> [a] -> Bool from prelude. It does exactly what it says on the label. To implement this function, I would use something like this:
elem = any . (==)
or even more elementary:
elem x = foldr ((||) . (x ==)) False
Notice that due to the short-circuit behaviour of (||) this also works with infinite lists as long as x is found.
The type of filter is (a -> Bool) -> [a] -> [a].
You have supplied the first argument which has type Char -> Bool (which is correct), then the second argument which is String (that's [Char]) which is correct, so the type of filter (\x -> x == c) s is [Char].
But the type signature you have provided says the function returns a Bool, which doesn't match the actual type returned.
You probably want to use any instead of filter. It's type is (a -> Bool) -> [a] -> Bool.
There's also an all function that returns True if and only if all elements of the list satisfy the predicate passed. You may also consider the functions or and and that given a [Bool] compute the disjunction or conjunction of the values. So any f = or . map f and all f = and . map f.
For all list-related functions see the Data.List module.

Resources