I'd like to define a function whose parameter takes in a list and an operator. This is what I currently have. I'm trying to define a higher order function that can find the minimum or the maximum.
largest :: (a -> a -> Bool) -> a
largest = findType (>)
findType :: (a -> a -> Bool) -> [a] -> a
findType op [] = error "empty list"
findType op [x] = x
findType op (x:xs)
| x op maxTail = x
| otherwise = maxTail
where maxTail = findType op xs
However, it's not currently working.
You can either write a function that accepts any a -> a -> Bool function parameter, or use the fact that comparable data types implement Ord class.
Here is a piece of code showing both methods to check if a list is sorted
option1 :: (a->a->Bool) -> [a] -> Bool
option1 op (a:b:ls) = op a b && option1 op (b:ls)
option1 op _ = True
option2 :: (Ord a) => Ordering -> [a] -> Bool
option2 op (a:b:ls) = compare a b == op && option2 op (b:ls)
option2 op _ = True
main = do
let ls = [1, 2, 3]
print $ option1 (<) ls
print $ option2 LT ls
Note that the 2nd method requires the use of Ordering data type which only has values LT, EQ and GT (meaning <, = and > respectively). You could make it more flexible by passing, say, a list of acceptable Ordering values or some other data structure, however, in most cases 1st option is more appropriate.
Your code as two different problems. Let's address the one generating the compiler error first.
You gave to findType the following signature:
findType :: (a -> a -> Bool) -> [a] -> a
the intent being to extract from the list given as the second parameter the bound as dictated by the ordering predicate provided as the first parameter.
However, in the last line of the very findType function definition, you bind maxTail to the expression findType xs, which omits the predicate.
The correct line is of course:
where maxTail = findType op xs
Your second error is related to the signature of the largest function, but I will let you find out exactly what it is.
GHC doesn't know that you want to use the function op as an operator into your code, you must tell him, but how can you do that ?
Let's consider the elem function, this function take a value and a list and return True or False depending if the value is present into the list or not.
elem :: Eq a => a -> [a] -> Bool
elem 2 [1,2,3] => True
Basically it's see as a function, and if you want to use them as an operator which can be really useful, you must enclose it with `.
2 `elem` [1,2,3] => True
If you add the remarks of didierc on the call of findType into the where clause, you'll have a working code.
Anyway, It's a very bad idea to put a recursive call into a guard, the code is hardest to read, and I'm not sure be it could lead to performance issue. You need to learn how to use an accumulator, take a look on this
Note
Conversely when a function is considered by default as an operator, to use it as a function just enclose it with ().
2 : [] => [2]
(:) 2 [] => [2]
Related
I'm making some exercise to practice my Haskell skills. My task is to implement the Haskell function find by myself with the filter function.
I already implemented the find function without the filter function (see codeblock below) but now my problem is to implement it with filter function.
-- This is the `find` function without `filter` and it's working for me.
find1 e (x:xs)= if e x then x
else find1 e xs
-- This is the find function with the filter function
find2 e xs = filter e xs
The result of find1 is right
*Main> find1(>4)[1..10]
Output : [5].
But my actual task to write the function with filter gives me the
*Main> find2(>4)[1..10]
Output : [5,6,7,8,9,10].
My wanted result for find2 is the result of find1.
To "cut a list" to only have one, head element in it, use take 1:
> take 1 [1..]
[1]
> take 1 []
[]
> take 1 $ find2 (> 4) [1..10]
[5]
> take 1 $ find2 (> 14) [1..10]
[]
If you need to implement your own take 1 function, just write down its equations according to every possible input case:
take1 [] = []
take1 (x:xs) = [x]
Or with filter,
findWithFilter p xs = take1 $ filter p xs
Your find1 definition doesn't correspond to the output you show. Rather, the following definition would:
find1 e (x:xs) = if e x then [x] -- you had `x`
else find1 e xs
find1 _ [] = [] -- the missing clause
It is customary to call your predicate p, not e, as a mnemonic device. It is highly advisable to add type signatures to all your top-level definitions.
If you have difficulty in writing it yourself you can start without the signature, then ask GHCi which type did it infer, than use that signature if it indeed expresses your intent -- otherwise it means you've coded something different:
> :t find1
find1 :: (t -> Bool) -> [t] -> [t]
This seems alright as a first attempt.
Except, you actually intended that there would never be more than 1 element in the output list: it's either [] or [x] for some x, never more than one.
The list [] type is too permissive here, so it is not a perfect fit.
Such a type does exist though. It is called Maybe: values of type Maybe t can be either Nothing or Just x for some x :: t (read: x has type t):
import Data.Maybe (listToMaybe)
find22 p xs = listToMaybe $ filter p xs
We didn't even have to take 1 here: the function listToMaybe :: [a] -> Maybe a (read: has a type of function with input in [a] and output in Maybe a) already takes at most one element from its input list, as the result type doesn't allow for more than one element -- it simply has no more room in it. Thus it expresses our intent correctly: at most one element is produced, if any:
> find22 (> 4) [1..10]
Just 5
> find22 (> 14) [1..10]
Nothing
Do add full signature above its definition, when you're sure it is what you need:
find22 :: (a -> Bool) -> [a] -> Maybe a
Next, implement listToMaybe yourself. To do this, just follow the types, and write equations enumerating the cases of possible input, producing an appropriate value of the output type in each case, just as we did with take1 above.
I need to calculate the minimum of a list but im trying to do it on this Type declaration
Ord a => a ‐> [a] ‐> [a]
which computes the list of those elements of the given list which are smaller than a
given argument (first argument of the function)
mymin :: Ord a => a-> [a] -> [a]
mymin (x:y:xs)
| x > y : mymin(y,xs)
|otherwise
Just use filter. It was made for filtering lists:
mymin :: Ord a => a -> [a] -> [a]
mymin x = filter (< x)
Note: after re-reading the question it seems you may just want to filter the list as mentioned in the other answers, my answer focuses on your initial requirement to find the minimum element of the list. I'll post it anyway, hopefully someone finds it useful.
Your guard syntax is incorrect, but you're almost there with what you've got. Take a look at the section called "Guards, guards!" in learn you a haskell. Guards let you include multiple statements like if a then b, if c then d in a function definition.
You need to include a definition for the otherwise case, you've left it off.
In your code you also should line up the | chars, the white space is significant and changes how the compiler/interpreter runs your program.
I think I can kind of see where you were going with mymin(y,xs) as if you were trying to pass back into your function of type Ord a => a-> [a] -> [a]. However as you've got it that won't work. Your current definition, mymin (x:y:xs) only matches Ord a => [a] -> [a], it's missing a parameter.
If you wanted to pass the smallest value along recursively you'd need to provide a definition like:
mymin :: (Ord a) => a -> [a] -> a
mymin x (y:ys)
Extending your work I've come up with the following. It returns the minimum element of the list but is not defined for an empty list (it will error). It's along the same lines as what you've got but keeps the smallest found item in the first index of the list, instead of passing it along as a separate function argument:
mymin :: Ord a => [a] -> a
mymin zs = head . mymin' $ zs
where mymin' (x:[]) = [x]
mymin' (x:y:xs)
| x > y = mymin' (y:xs)
| otherwise = mymin' (x:xs)
You should probably be reading some basic Haskell guides... Still, two hints to get you going with this problem:
Start with the base case: What's the expected output for an empty list and arbitrary pivot element?
mymin takes two arguments, so the first line of your code should probably be mymin y (x:xs)
Edit: On second thought, have you thought about using filter?
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
isTogether' :: String -> Bool
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
For the above code, I want to go through every character in the string. I am not allowed to use recursion.
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
If I've got it right, you are interested in getting consequential char pairs from some string. So, for example, for abcd you need to test (a,b), (b,c), (c,d) with some (Char,Char) -> Bool or Char -> Char -> Bool function.
Zip could be helpful here:
> let x = "abcd"
> let pairs = zip x (tail x)
it :: [(Char, Char)]
And for some f :: Char -> Char -> Bool function we can get uncurry f :: (Char, Char) -> Bool.
And then it's easy to get [Bool] value of results with map (uncurry f) pairs :: [Bool].
In Haskell, a String is just a list of characters ([Char]). Thus, all of the normal higher-order list functions like map work on strings. So you can use whichever higher-order function is most applicable to your problem.
Note that these functions themselves are defined recursively; in fact, there is no way to go through the entire list in Haskell without either recursing explicitly or using a function that directly or indirectly recurses.
To do this without recursion, you will need to use a higher order function or a list comprehension. I don't understand what you're trying to accomplish so I can only give generic advice. You probably will want one of these:
map :: (a -> b) -> [a] -> [b]
Map converts a list of one type into another. Using map lets you perform the same action on every element of the list, given a function that operates on the kinds of things you have in the list.
filter :: (a -> Bool) -> [a] -> [a]
Filter takes a list and a predicate, and gives you a new list with only the elements that satisfy the predicate. Just with these two tools, you can do some pretty interesting things:
import Data.Char
map toUpper (filter isLower "A quick test") -- => "QUICKTEST"
Then you have folds of various sorts. A fold is really a generic higher order function for doing recursion on some type, so using it takes a bit of getting used to, but you can accomplish pretty much any recursive function on a list with a fold instead. The basic type of foldr looks like this:
foldr :: (a -> b -> b) -> b -> [a] -> b
It takes three arguments: an inductive step, a base case and a value you want to fold. Or, in less mathematical terms, you could think of it as taking an initial state, a function to take the next item and the previous state to produce the next state, and the list of values. It then returns the final state it arrived at. You can do some pretty surprising things with fold, but let's say you want to detect if a list has a run of two or more of the same item. This would be hard to express with map and filter (impossible?), but it's easy with recursion:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:y:xs) | x == y = True
hasTwins (x:y:xs) | otherwise = hasTwins (y:xs)
hasTwins _ = False
Well, you can express this with a fold like so:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:xs) = snd $ foldr step (x, False) xs
where
step x (prev, seenTwins) = (x, prev == x || seenTwins)
So my "state" in this fold is the previous value and whether we've already seen a pair of identical values. The function has no explicit recursion, but my step function passes the current x value along to the next invocation through the state as the previous value. But you don't have to be happy with the last state you have; this function takes the second value out of the state and returns that as the overall return value—which is the boolean whether or not we've seen two identical values next to each other.
How to write a function that takes a predicate f and a list xx and reutrns true if fx is true for some x∈xs?
For example:
ghci>exists (>2) [1,2,3]
True
This is the function I wrote:
exists :: (t->Bool)->[t]->Bool
exists f a []=error
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
I know this is not right, but I don't know why. Do I need to write this predicate function f first, then used it inside the function exists. Because I really don't know how to compare one element of list xs with the function.
Your desired example usage is this
ghci>exists (>2) [1,2,3]
True
Stop. Hoogle time. ( <------ This should be the Haskell motto imho)
You want a function ("exists") that takes two parameters. The first is a unary function (a -> Bool) and the second is a list [a]. The desired result is a Bool
Hoogling that type signature, (a -> Bool) -> [a] -> Bool, the top hits are any, all, and find. As Andrew has noted, any is the one that behaves like the "exists" function.
As a side note, my first thought was to use find, which returns a Maybe a, and then pattern match. If it returns Nothing, then the result would be False, otherwise True.
As another side note, the actual implementation is simply any p = or . map p.
The third side note is probably the answer to your actual question. How is map defined? Hoogle is once again your friend. Search for the method's name and you can find a page that links to the source. I suggest you do this for map and or, but will only show map here.
map _ [] = []
map f (x:xs) = f x : map f xs
That's the basic way to recurse over a list. recursiveCall f (x:xs) = f x : recursiveCall f xs But if it can be written with map, filter, or foldl/foldr, then you should do it with these recursive methods. (Stop. Hoogle time. Search for those method names and check out the source; it's pretty straightforward.)
If we take a look at your definition,
exists :: (t -> Bool) -> [t] -> Bool
exists f a []=error
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
We see that your type is
exists :: (t -> Bool) -> [t] -> Bool
So exists must take two parameters, one predicate function of type (t -> Bool) and one list of type [t]. It returns a Bool. This seem okay as per our intention of the specification.
Let us look at the first line of your terms:
exists f a [] = error
This function suddenly takes three parameters. The f and the empty list constructor [] looks okay, but the a is not mentioned in the type specification. Hence, we prune it out:
exists f [] = error
Now, the error returned is not of boolean value. But the spec says it must be. Let us suppose we are asking exists (<2) []. Then would a natural answer to the question be True or False? Or paraphrased, is there any element x in [] satisfying the predicate f x ?
On to the next line,
exists f a (x:xs)
|if x∈f a =True
|otherwise= x:f a xs
We learned that the a has to go by the type specification, so let us prune it. Since we have now grown a natural dislike for the a, why not prune it everywhere it occur. Also, since the if will produce a syntax error, lets rid ourselves of that too:
exists f (x:xs)
| x∈f = True
| otherwise = x:f xs
The x∈f does not make much sense, but f x does. The guard variant will be taken if f x returns true. Now, the True which is returned here sounds about right. It signifies that we have found an element in the list matching the predicate - and lo n' behold, x might be it!
So we turn our attention to the final line. The otherwise means that the guard f x did not return True. As a consequence, the x is not satisfying the predicate, so we must search the rest of the list.
The Right-hand-side x : f xs is peculiar. The : means that we will try to return a list, but the return type of the function is something of type Bool. The type checker won't like us if we try this. Furthermore, we have no reason to look at the x anymore since we just determined it does not satisfy the predicate.
The key thing you are missing is that we need recursion at this point. We need to search the tail xs of the list somehow - and recursion means to invoke the exists function on the tail.
Your general track is right, but ask again if something is unclear. One trick might be to go by the types for the recursion case: "What do i have to supply exists for it to return a Bool value?".
I think the function you want already exists -- any:
Prelude> :t any
any :: (a -> Bool) -> [a] -> Bool
Prelude> any (<3) [1, 2, 3, 4]
True
Prelude> any (<3) [3, 4, 5, 6]
False
And then, in the spirit of your question -- not just getting a working function but working out how it's done -- we can look up the definition in the prelude:
any p xs = or (map p xs)
We map the function over the list to get a new [Bool] list, and then check with or to see if any of them are True, which by the way thanks to lazy evaluation short circuits as needed:
Prelude> any (<3) [1, 2..]
True
Actually your original version wasn't too far from working. To fix it, write:
exists :: (t -> Bool) -> [t] -> Bool
exists _ [] = False
exists f (x:xs)
| f x = True
| otherwise = exists f xs
Instead of using x in f, just apply f to x using f x as the predicate in the if statement. Your otherwise clause should also return a Bool: the result of exists on the rest of the list.