Higher Order Functions evaluation - haskell

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

Related

Why is the type for [tail, init, reverse], [[a] -> [a]]?

This question is in one of the Haskell textbook exercises, not so smart question.
Question: What are the types of the following values?
[tail, init, reverse]
Solution: [[a] -> [a]]
But why?
tail, init and reverse are functions defined on a generic list, [a]. You read [a] as "a list of any type abstracted as a", in particular, if a = Int, you get [Int] - list of integers.
Now, function that takes a list and outputs a list of the same type has signature [c] -> [c] or, if c = a, [a] -> [a]. The letter picked up does not matter as long as you have the same latter on both sides, because [a] -> [b] would mean that you take somehow a list of as and map it to a list of bs - which - in general - a different type. You could say that a = Int and b = String and therefore you'd have to map Int to String anyhow; also you could say that b = a an thus reduce to the [a] -> [a] case.
The last one: [tail, init, reverse] is obviously yet another list, where a = [b] -> [b]. So you got [ [b] -> [b] ] type or, equivalently, [ [a] -> [a] ] or [ [k] -> [k] ]. Again: particular letter does not matter as long as you stick to the chosen one.
The type of the following value, not "values". singular. List of three elements is a value. Or did you mean "each of the values in the given list"? then they all must have the same type. since a list has a type [t] for some t. which implies all its elements have that same type t, whatever that is. then since tail :: [a] -> [a], so must be the other two that appear in the same list.
On their own they could each refer to a different letter i.e. "type variable". but inside the same list, they all must be in agreement. thus the type of the list as a whole is [ [a] -> [a] ].

Attempting to model operators for Integrated Dynamics

Integrated Dynamics is a Minecraft mod that uses lazy operators with currying, and acts very similarly to Haskell. I've been writing functions that have the same signature though do not perform anything to try and more easily explore combining the operators. An example is itemName :: Item -> String with itemName _ = "".This is to give in ghci :t itemName as Item -> String.
I've tried to make a couple slightly more complicated ones such as
itemListCount :: (Num c) => [a] -> b -> c
itemListCount _ _ = 0
I'd like to see the signature of this if I pipe it directly with greater than or less than, expecting to see something like [a] -> b -> c -> d. a List, an Item(custm data type) an integer and return a boolean. when calling with :t (lessThan . itemListCount) This gives error:
Couldn't match type 'b0 -> Integer' with 'Int'.
Expected type: [a] -> Int
Actual type: [a] -> b0 -> Integer
Is this because I'm calling it with :t that it's trying to evaluate instead of combining the functions?
(lessThan . itemListCount) is the same as \x -> lessThan (itemListCount x). It's a function, which takes one value, then calls itemListCount with this value, and then calls lessThan with whatever itemListCount returned.
itemListCount's type is (ignoring the Num constraint) [a] -> b -> c. It is a function which takes a list of any type, and then returns a function which takes any type as input and returns any number type as output.
So in \x -> lessThan (itemListCount x), x should be a list of any type, and (itemListCount x) is a function which takes any type as input and returns any number type as output. Presumably, this is not a valid argument for lessThan.

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.

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.

How to create a base case for a tuple in Haskell?

I have the following function:
encode_single :: (Eq a) => [a] -> (Int, a)
encode_single (x:xs) = (count xs + 1, x)
However, Haskell complained about needing a base case, but I don't know how to do this because of the generic a type.
Thanks!
First of all, what you received is only a warning, not an error. Haskell does not need the base case of the empty list, it just suggests it.
Partial functions are most often an anti-pattern in functional programming so it just points out something that may be wrong. You can avoid the warning in different ways.
The first one is to make your function safe: if it cannot always return a value it's return type shouldn't be (Int, a) but Maybe (Int, a), so you could do:
encode_single :: (Eq a) => [a] -> Maybe (Int, a)
encode_single [] = Nothing
encode_single (x:xs) = Just (count xs + 1, x)
Otherwise you'd have to return a meaningful value for the empty case (just returning undefined isn't better than not defining that case). It might be appropriate to do somethign like:
encode_single [] = (0, undefined)
However this assumes that any code that uses the result of encode_single will not evaluate the second element of the tuple if the first element is zero (note that if the list isn't empty the first element is always positive, so 0 can be used as a sentinel value).
This may or may not be the case. However one thing is sure: this is not compile-time safe so you may receive some run-time errors when calling such a function.
Simply enough: at the type you desire you cannot write a total function of that specification. You need to change the type.
You can either add a default a or indicate partiality using Maybe.
encode_single :: a -> [a] -> (Int, a)
encode_single :: [a] -> Maybe (Int, a)
if you cannot change the type signature, you can piggyback on head i.e.
encode_single :: [a] -> (Int, a)
encode_single a = (length a, head a)
obviously, empty list input is not handled properly.

Resources