I'm learning Haskell and there's a lot of type-checking that seems completely nonsensical to me. I have written a simple function to count the number of occurrences of a given element in a given list, as such:
-- Count the number of occurrences of an element in a list.
countOcc :: (Eq a) => [a] -> a -> Int
countOcc xs x = length $ filter (== x) xs
Now, using this explicitly with calls such as:
countOcc "str" 's'
This executes fine, and returns correctly. However, this causes an error:
countOcc "str" "str"!!0
I haven't the foggiest why this should cause an error. "str"!!0 gives 's', a Char, which is exactly the same type passed in the second parameter of the first call.
I'm sure there are some nuances to Haskell's type system that I'm overlooking, or haven't broached yet. Ideally, I'd like to know why this is erroneous and furthermore, I'd like to know, according to Haskell's ideology, why it should be erroneous.
The following works fine:
countOcc :: (Eq a) => [a] -> a -> Int
countOcc xs x = length $ filter (== x) xs
main = print $ countOcc "str" ("str"!!0) -- 1
As far as I know, function applictaion has the highest precedence; although !! has precedence level of 9, it is still lower than function application.
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 have started to solve the 99 problems in Haskell, and for the second question, it is given the following solution:
myButLast' :: [a] -> a
myButLast' = last . init
and if we give the empty list to this function, we get and error, however, I would like to print a specific error as
myButLast' [] = error "The list has to have at least 2 elements!"
myButLast' [x] = error "The list has to have at least 2 elements!"
but when I add these line to the code, I get
Equations for ‘myButLast'’ have different numbers of arguments
, so is there a way to use the composition type of defining my new function while also adding some specific behaviour ?
The best you can do is probably something like the following, where the error checking is moved into an auxiliary function (which I've named go for lack of a better name) defined in a where clause:
myButLast :: [a] -> a
myButLast = go (last . init)
where
go _ [] = bad
go _ [x] = bad
go f xs = f xs
bad = error "The list has to have at least 2 elements!"
It might help make it clearer what's going on if we define go separately with a type signature. Also, in case you find the underscores confusing, I've replaced them with f:
myButLast :: [a] -> a
myButLast = go (last . init)
go :: ([a] -> a) -> [a] -> a
go f [] = bad
go f [x] = bad
go f xs = f xs
bad = error "The list has to have at least 2 elements!"
Here, you can see that go is a function that takes two arguments, the first being itself a function of type [a] -> a and the second being a list of type [a].
The above definition of go pattern matches on the second argument (the list). If the list is empty or a singleton, then the result of go is just bad (the error message), regardless of the function f. Otherwise (if the list is at least two elements), the result of go f xs is simply to apply the first argument (that function f) to the list xs.
How does this work? Well, let's see what happens if we apply myButLast to a list. I've used the symbol "≡" here to show equivalence of Haskell expressions with comments explaining why they are equivalent:
myButLast [1,2,3]
-- by the definition of "myButLast"
≡ go (last . init) [1,2,3]
-- by the definition of "go", third pattern w/
-- f ≡ last . init
-- xs = [1,2,3]
≡ (last . init) [1,2,3] -- this is just f xs w/ the pattern substitutions
-- because of your original, correct answer
≡ 2
If we apply it to a "bad" list, the only difference is the pattern matched from the definition of go:
myButLast [1]
-- by the definition of "myButLast"
≡ go (last . init) [1]
-- by the definition of "go", second pattern w/
-- f ≡ last . init
-- x = 1
≡ bad
-- gives an error message by definition of "bad"
As an interesting aside, another way to look at go is that it's a function:
go :: ([a] -> a) -> ([a] -> a)
Because the function application arrow -> is right associative, this type signature is exactly the same as ([a] -> a) -> [a] -> a. The neat thing about this is that now it's clear that go takes a function of type [a] -> a (such as last . init) and returns another function of type [a] -> a (such as myButLast). That is, go is a transformer that adds additional behavior to an existing function to create a new function, which is exactly what you were asking for in your original question.
In fact, if you slightly generalize the type signature so that go can operate on a function taking a list, regardless of what it returns:
go :: ([a] -> b) -> [a] -> b
go _ [] = bad
go _ [x] = bad
go f xs = f xs
this still works. Then, you could use this same go on anything that needed a list of length two, whatever it returned. For example, if you had an original implementation to return the last two elements of a list:
lastTwoElements :: [a] -> [a]
lastTwoElements = (!! 2) . reverse . tails -- tails from Data.List
you could re-write it as:
lastTwoElements :: [a] -> [a]
lastTwoElements = go ((!! 2) . reverse . tails)
to add error handling for the empty and singleton list cases.
In this case, you'd probably want to rename go to usingTwoElements or withList2 or something...
Use an explicit argument in the solution:
myButLast' x = last (init x)
Now you can add your special cases just above that line.
The original solution used a pointfree style last . init to avoid mentioning the x argument. However, if you have to add further equations, you need to make the argument explicit.
Moving from
fun :: A -> B
fun = something
to
fun :: A -> B
fun a = something a
is called eta-expansion, and is a common transformation of Haskell code. The first style is usually called point-free (or, jokingly, point-less), while the second one is called pointful. Here "point" refers to the variable a.
Somewhat sidestepping the original question, but you may be interested in the safe package for tasks like this. In general, you should strive to use total functions that don't raise errors. In this case, that means using something like lastMay :: [a] -> Maybe a and initMay :: [a] -> Maybe a, which simply return Nothing if given an empty list. They can be composed using <=<, found in Control.Monad.
import Safe
myButLast :: [a] -> Maybe a
myButLast = lastMay <=< initMay
Then
> myButLast []
Nothing
> myButLast [1]
Nothing
> myButLast [1,2]
Just 1
If you really want an error message, Safe provides lastNote and initNote as well.
myButLast = let msg = "Need at least 2 elements" in (lastNote msg . initNote msg)
You could often simply compose an additional function that has the additional behaviour:
myButLast' :: [a] -> a
myButLast' = last . init . assertAtLeastTwo
where assertAtLeastTwo xs#(_:_:_) = xs
assertAtLeastTwo _ = error "The list has to have at least 2 elements!"
Here we've added a function that checks for the conditions we want to raise an error, and otherwise simply returns its input so that the other functions can act on it exactly as if assertAtLeastTwo wasn't there.
Another alternative that allows you to clearly highlight the error conditions is:
myButLast' :: [a] -> a
myButLast' [] = error "The list has to have at least 2 elements!"
myButLast' [x] = error "The list has to have at least 2 elements!"
myButLast' xs = go xs
where go = last . init
Where you do the error checking as you originally wrote, but have the main definition simply defer to an implementation function go, which can then be defined point-free using composition.
Or you can of course inline go from above, and have:
myButLast' xs = (last . init) xs
Sine a composition of functions is itself an expression, and can simply be used in a larger expression directly as the function. In fact a fairly common style is in fact to write code of the form "compose a bunch of functions then apply to this argument" this way, using the $ operator:
myButLast' xs = last . init $ xs
If you would use wrappers you can have the best of both worlds and a clear separation between the two. Robust error checking and reporting and a vanilla function to use however you wish, with or without the wrapper.
Interesting, the vanilla function reports 'last' cannot process an empty list given a one element list and 'init' cannot process an empty list when given an empty list.
mbl2 = last . init
mbl xs = if length xs < 2 then error errmsg else mbl2 xs
where errmsg = "Input list must contain at least two members."
This is my second day learning Haskell and I am stuck terribly by a problem.
I tried to solve the eighth problem in 99 Haskell questions
The problem is to write a function called "compress" which works like this:
>compress "aaaabbbbccccddddd"
"abcd"
>compress [1,1,1,1,2,3,4,4,4,4]
[1,2,3,4]
and here's what I wrote:
compress :: (Eq a) => [a] -> [a]
compress [] = []
compress x = filter ( (head x) `notElem` ( compress $ tail x ) ) x
The compiler said:
Couldn't match expected type a -> Bool' with actual type Bool'
In compress, I tried to recursively pick up new elements from end to head. (like backtracking maybe??)
Is my algorithm wrong?
Is there alternative way to implement the algorithm in a more readable way?
(Like: where to put parentheses? or $ )
Can someone kindly help me with it?
Thanks a lot.
Thanks to Lubomir's help, I corrected my code by :
compress'(x:xs) = x : compress' (dropWhile (== x) xs)
and it works!
And thanks everyone, I feel spoiled! You guys are so kind!
I'll keep on learning Haskell!
Is there alternative way to implement the algorithm in a more readable
way?
Yes.
import Data.List
compress :: Eq a => [a] -> [a]
compress = map head . group
map head . group is basically \xs -> map head (group xs). group xs will create a list of lists were all equal consecutive elements are grouped together in a list. map head will then take the heads of these lists discarding the rest as required.
The algorithm is basically fine, but it does not typecheck. The first argument to filter should be a function of type a -> Bool – for an element of the list it should tell you whether or not to throw it out. What you have is a single Bool value.
The second part of the function may be better implemented with a different pattern. This would allow you to drop the head and tail functions.
compress [] = []
compress (x:xs) = x : compress (filter (/= x) xs)
This pattern binds x to the first element of the list and xs is the tail of the list. The function should include x in the result and recursively call itself on filtered xs (with x removed from it).
EDIT: this function does not do what the problem requests. Only consecutive duplicates should be eliminated. This can be fixed by using dropWhile instead of filter and slightly modifying the predicate function.
Check the signature of filter:
Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]
Note that the first argument must be a function. Now check the type of your expression within the paranthesis.
Prelude> :t notElem
notElem :: Eq a => a -> [a] -> Bool
Thus, notElem a b will return a value of type Bool.
Note: I think you might have misunderstood the problem statement. What is the expected output for aaabbbaaa?
I would argue it should be aba, as the problem is stated as
Eliminate consecutive duplicates of list elements.
(emphasize mine).
First time poster, but this site has helped me alot.
I am trying to learn Haskell.
This is the question i'm asked to answer.
Write a function that takes a list (length >=2) of pairs of length and returns the first component of the second element in the list. So, when provided with [(5,’b’), (1,’c’), (6,’a’)], it will return 1.
I have done this myself.
listtwo :: [([a],b)] -> [a]
listtwo [] = []
listtwo [(a,b)] = fst (head (tail [(a,b)]))
I am trying to take a list of lists tuples I believe and return the 1st element from the 2nd item in the list. I know if you take out the [(a,b)]'s and replace the second [(a,b)] with a list like the one in the question it works fine. But when I try to make this function work for ANY list of tuples. I get errors.
Error I recieve
<interactive>:1:27:
No instance for (Num [a0])
arising from the literal `6'
Possible fix: add an instance declaration for (Num [a0])
In the expression: 6
In the expression: (6, 'a')
In the first argument of `listtwo', namely
`[(5, 'b'), (1, 'c'), (6, 'a')]'
So i'm asking if anyone can help me deciver the errors and mabye explain what I am doing wrong (don't give me the answer, cant learn that way).
Appriciate the help, might have more questions if this gets answered. Thank you very much in advance!
You say that you want a function that returns the first component of the second element of the list. The best way to write this function will be by pattern matching. But first, let's think about its type.
Say you want a list of tuples of (Int,Char). This is written as [(Int,Char)]. If you want a list of 2-tuples of arbitrary type, you replace the types Int and Char with type variables, so you end up with the type [(a,b)].
Your function needs to take something of this type, and return the first component of the second element of the list. All of the first components of the tuples have type a, so your return type must be a as well. So your function's type signature is
f :: [(a,b)] -> a
Now, how do we write this function? The best way is to use pattern matching. This is a neat way to extract the components of a data structure without having to use accessors (aka getters, if you come from an object-oriented background). Let's say we have a function g :: [a] -> a which returns the third component of a list. You could write
g :: [a] -> a
g xs = head (tail (tail xs))
but that looks pretty nasty. Another way is to pattern match. A list with three elements [x,y,z] can be constructed by doing x : y : z : [] where x, y and z are all of type a (remember that the operator : adds items to the front of a list). So we can write:
g :: [a] -> a
g (x : y : z : []) = z
But there's a problem with this - it only works on lists of length three, because our pattern says "Match a list of three elements with the empty list tacked on the end." Instead, we could use the pattern x : y : z : rest, where now rest matches the rest of the list:
g :: [a] -> a
g (x : y : z : rest) = z
where our pattern now says "Match a list of three elements followed by anything else at all." In fact, we can make it simpler. We aren't going to use the values x, y or rest so we can replace them with the Haskell pattern _ (underscore). This matches anything, and makes us promise that we aren't going to use that value:
g :: [a] -> a
g (_ : _ : z : _) = z
How can we use this to solve your problem? Well, if you had a list matching the pattern (w,x) : (y,z) : rest you would want to return y. So you can write:
f :: [(a,b)] -> a
f ( (w,x) : (y,z) : rest ) = y
which will work fine. However, you don't care about the first pair at all, so you can replace (w,x) with _. You also don't care about the second element of the second tuple or the rest of the list, so you can replace them with _ as well, getting:
f :: [(a,b)] -> a
f ( _ : (y,_) : _) = y
Checking it in ghci:
ghci> f [(5,'b'),(1,'c'),(6,'a')]
1
So it behaves as you expected it to.
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.