what does ((Ord, Ord) -> Bool) -> [String] -> String mean in haskell - 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.

Related

Higher Order Functions evaluation

Create a high-order function in Haskell that takes in another function. That second function takes in a list and evaluates to each index to be true or false. The high order function should evaluate to true if the second function evaluates to true for at least 2 indexes in the list
This is what I have so far
Bool _ _ = []
Bool f (x y :xs) = f x y : Bool f xs
Split your task into subtasks:
Create a high-order function in Haskell that takes in another function.
higherOrder :: (a -> b) -> Bool
higherOrder f = undefined -- a higher order function that takes
-- in another function
We have not learned anything about the type of the passed function, which is why we use the placeholder a -> b. This will be change later, once we learn more about f.
That second function takes in a list and evaluates to each index to be true or false.
This function is passed in. You don't need to implement it, it will be provided as an argument. You do however need to know its type signature, in this case
f :: [a] -> [Bool] -- a function taking a list of any type
-- ([a]), evaluating it to a list of booleans
-- example usage
f [1, 2, 3] == [True, False, True]
Which we use to update the type of our higherOrder
higherOrder :: ([a] -> [Bool]) -> Bool
The high order function should evaluate to true if the second function evaluates to true for at least 2 indexes in the list
You could replace this step with a simpler step: Write a function atLeastTwo :: [Bool] -> Bool, that takes a list of Booleans ([Bool]) and returns True if at least two indexes' values are true.
atLeastTwo :: [Bool] -> Bool
atLeastTwo xs = undefined
Maybe you can implement atLeastTwo by filtering the list, keeping only True values and then counting its length. You might find filter :: (a -> [Bool]) -> [a] -> [a] and length :: [a] -> Int1 useful.
Putting it all together you will discover that the task description is not clear. It does not talk about the list that is passed to higherOrder. In your case it probably should have been passed as a second parameter (xs) so we update higherOrder again to
higherOrder :: ([a] -> [Bool]) -> [a] -> Bool
higherOrder f xs = undefined
Proposal for an updated assignment
A more natural problem would be, where the passed function processes a list element (a -> Bool) instead of a list ( [a] -> [Bool]), and would read:
[Updated/alternative assignment: replacing ([a] -> [Bool]) with (a -> Bool).]
Implement a (higher-order) function atLeastTwoTrues :: (a -> Bool) -> [a] -> Bool. The first argument being passed to atLeastTwoTrues should be a function that can evaluate a value to either True or False. The second argument is a list of values. Your function should return True if and only if at least two elements of the passed list evaluate to True using the first argument.
This would avoid some ambiguity but is a different problem.
Good luck and enjoy your Haskell journey. It is difficult at the start. It has been for all of us. Don't give up, because once you start to master it, you will enjoy it.
1This is actually not the complete truth since length works with more data types than just lists and has a more general type.
Prelude> :t length
length :: Foldable t => t a -> Int

Re-write 'map intToDigit' with a fold...

So this one seems like it should be super-simple... but I'm not sure where to stick the 'fold' in (obviously you could fold either way)...
It says "write a function ( intToString :: [Int] -> [Char] ) using a fold, that mimics this map:
map intToDigit [5,2,8,3,4] == "52834"
And then says, "For the conversion, use intToDigit :: Int -> Char from Data.Char."
I'm not entirely sure I get the point... but yet it doesn't seem like it should be that hard -- you're just reading in the list (folding it in, I get how folds work in general) from either the left or right and doing the conversion... but I'm not sure how to set it up.
It is not difficult, think about the definition foldr (or foldl) of List:
foldr::(a -> b -> b) -> b -> [a] -> b
Here (a->b->b) is the step function which will be applied on each element of list [a], b is your target.
Now, you have a list of Int ([Int]), and need to convert to [Char] (or String).
Relpace [a] by [5,2,8,3,4], b by []::[Char] (your target) and (a->b->b) by step function :
foldr step ([]::[Char]) [5,2,8,3,4]
We have known that step function has type (a->b->b), specifically, (Int->[Char]->[Char]), the job need to do just convert Int to [Char], as mentioned in question: intToDigit can be helped to convert Int to Char and (:) operator can append element at the head of List so:
step x s = intToDigit x : s
where s is [Char] (or String), put them all:
foldr (\x s->intToDigit x : s) [] [5,2,8,3,4]

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.

Checking for all lowercase & Combining a Word with a List - 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.

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