So, I am trying to implement a function that, given a list of 3 elements ((Int,Int),Int), returns True when on the second position is the same value for all 3 and False otherwise.
For instance, [((1,2),7),((5,3),7),((1,9),7)] should return True and [((1,2),3),((5,3),3),((1,9),5)] should return False.
Here is my code:
bc :: [((Int,Int),Int)]
wcheck :: [((Int,Int),Int)] -> Bool
wcheck bc
| (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
| otherwise = False
And the error that I get:
E:\\study related\Module1\week 4\ttt.hs:55:65: error:
* Couldn't match expected type `[(a, b0)]'
with actual type `((a, b), (a, b1))'
* In the first argument of `last', namely `bc'
In the first argument of `fst', namely `(last bc)'
In the second argument of `(==)', namely `fst (last bc)'
* Relevant bindings include
bc :: ((a, b), (a, b1))
(bound at E:\\study related\Module1\week 4\ttt.hs:54:8)
wcheck :: ((a, b), (a, b1)) -> Bool
(bound at E:\\study related\Module1\week 4\ttt.hs:54:1)
|
55 | | (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
|
Could you please tell me why I get this error and a way to fix it? Thank you.
It will probably be easier if we perform simple pattern matching instead of using fst :: (a, b) -> a, etc.
Second item of the first item of the tuple
We can use a pattern ((_, x), _) to obtain the second element from such 2-tuple wrapped in a 2-tuple.
So we can use pattern matching like:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [((_, x), _), ((_, y), _), ((_, z), _)] = x == y && y == z
wcheck _ = False
So here if the list contains three elements, we unpack the elements, and then check if the "second item"s are equal to each other. In case the pattern does not match (for a list with too few, or too much elements), we just return False.
But a "list of three elements" does not make much sense. In case the number of elements is known at compile time, it is better to use a tuple, since in that way, the compiler can verify that you can only provide 3-tuples to that function.
Second item of the tuple
In case we are interested in the second item of the tuple, we can use (_, x) as pattern (we are not interested in the first item whatsoever):
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
Note that we can generalize the signature with:
wcheck :: Eq c => [((a, b), c)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
fst and snd are not very nice in this situation. We can extract the bit we care about by doing a pattern match:
let (_,y) = x in ...
Now you want to do that to each element of your list (to check that every element has the same second value):
map (\(_,x) -> x)
And then you want to check that they are all equal:
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual (x:xs) = all (\y->x==y) xs
This gets the first element, x, from a list (if it exists) and checks that ever other item y satisfies the test that x==y
So we can now write your function:
wcheck xs = allEqual (map (\(_,y) -> y) xs)
Given that you want to test the equality of the second element of the outer pair, there are so many ways to do this, including the following.
First, fmapping snd gives you these elements:
λ> fmap snd [((1,2),7),((5,3),7),((1,9),7)]
[7,7,7]
Now you can group them to lists of consecutive equal numbers:
λ> import Data.List
λ> (group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
[[7,7,7]]
The values are equal if the length of this list of lists is at most one (assuming an empty list of such pairs is defined to have equal second elements):
λ> (length . group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
1
Putting these together we can define
import Data.List
equalSnds :: Eq a => [(b, a)] -> Bool
equalSnds xs = (length . group . fmap snd) xs <= 1
So that
λ> equalSnds [((1,2),7),((5,3),7),((1,9),7)]
True
λ> equalSnds [((1,2),3),((5,3),3),((1,9),5)]
False
If you want to also test for the length of the list, you can do it separately:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck xs = length xs == 3 && equalSnds xs
Related
I m a newbie to Haskell. I am pretty good with Imperative languages but not with functional. Haskell is my first as a functional language.
I am trying to figure out, how to get the index of the smallest element in the list where the minimum element is defined by me.
Let me explain by examples.
For example :
Function signature
minList :: x -> [x]
let x = 2
let list = [2,3,5,4,6,5,2,1,7,9,2]
minList x list --output 1 <- is index
This should return 1. Because the at list[1] is 3. It returns 1 because 3 is the smallest element after x (=2).
let x = 1
let list = [3,5,4,6,5,2,1,7,9,2]
minList x list -- output 9 <- is index
It should return 9 because at list[9] is 2 and 2 is the smallest element after 1. x = 1 which is defined by me.
What I have tried so far.
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = length ys
| otherwise = m
where m = minListIndex x ys
When I load the file I get this error
• Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
minListIndex :: forall a. (Ord a, Num a) => a -> [a] -> a
at myFile.hs:36:17
• In the expression: 1 + length ys
In an equation for ‘minListIndex’:
minListIndex x (y : ys)
| x > y = 1 + length ys
| otherwise = 1 + m
where
m = minListIndex x ys
• Relevant bindings include
m :: a (bound at myFile.hs:41:19)
ys :: [a] (bound at myFile.hs:38:19)
y :: a (bound at myFile.hs:38:17)
x :: a (bound at myFile.hs:38:14)
minListIndex :: a -> [a] -> a (bound at myFile.hs:37:1)
When I modify the function like this
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = 2 -- <- modified...
| otherwise = 3 -- <- modifiedd
where m = minListIndex x ys
I load the file again then it compiles and runs but ofc the output is not desired.
What is the problem with
| x > y = length ys
| otherwise = m
?
In short: Basically, I want to find the index of the smallest element but higher than the x which is defined by me in parameter/function signature.
Thanks for the help in advance!
minListIndex :: (Ord a, Num a) => a -> [a] -> a
The problem is that you are trying to return result of generic type a but it is actually index in a list.
Suppose you are trying to evaluate your function for a list of doubles. In this case compiler should instantiate function's type to Double -> [Double] -> Double which is nonsense.
Actually compiler notices that you are returning something that is derived from list's length and warns you that it is not possible to match generic type a with concrete Int.
length ys returns Int, so you can try this instead:
minListIndex :: Ord a => a -> [a] -> Int
Regarding your original problem, seems that you can't solve it with plain recursion. Consider defining helper recursive function with accumulator. In your case it can be a pair (min_value_so_far, its_index).
First off, I'd separate the index type from the list element type altogether. There's no apparent reason for them to be the same. I will use the BangPatterns extension to avoid a space leak without too much notation; enable that by adding {-# language BangPatterns #-} to the very top of the file. I will also import Data.Word to get access to the Word64 type.
There are two stages: first, find the index of the given element (if it's present) and the rest of the list beyond that point. Then, find the index of the minimum of the tail.
-- Find the 0-based index of the first occurrence
-- of the given element in the list, and
-- the rest of the list after that element.
findGiven :: Eq a => a -> [a] -> Maybe (Word64, [a])
findGiven given = go 0 where
go !_k [] = Nothing --not found
go !k (x:xs)
| given == xs = Just (k, xs)
| otherwise = go (k+1) xs
-- Find the minimum (and its index) of the elements of the
-- list greater than the given one.
findMinWithIndexOver :: Ord a => a -> [a] -> Maybe (Word64, a)
findMinWithIndexOver given = go 0 Nothing where
go !_k acc [] = acc
go !k acc (x : xs)
| x <= given = go (k + 1) acc xs
| otherwise
= case acc of
Nothing -> go (k + 1) (Just (k, x)) xs
Just (ix_min, curr_min)
| x < ix_min = go (k + 1) (Just (k, x)) xs
| otherwise = go (k + 1) acc xs
You can now put these functions together to construct the one you seek. If you want a general Num result rather than a Word64 one, you can use fromIntegral at the very end. Why use Word64? Unlike Int or Word, it's (practically) guaranteed not to overflow in any reasonable amount of time. It's likely substantially faster than using something like Integer or Natural directly.
It is not clear for me what do you want exactly. Based on examples I guess it is: find the index of the smallest element higher than x which appears after x. In that case, This solution is plain Prelude. No imports
minList :: Ord a => a -> [a] -> Int
minList x l = snd . minimum . filter (\a -> x < fst a) . dropWhile (\a -> x /= fst a) $ zip l [0..]
The logic is:
create the list of pairs, [(elem, index)] using zip l [0..]
drop elements until you find the input x using dropWhile (\a -> x /= fst a)
discards elements less than x using filter (\a -> x < fst a)
find the minimum of the resulting list. Tuples are ordered using lexicographic order so it fits your problem
take the index using snd
Your function can be constructed out of ready-made parts as
import Data.Maybe (listToMaybe)
import Data.List (sortBy)
import Data.Ord (comparing)
foo :: (Ord a, Enum b) => a -> [a] -> Maybe b
foo x = fmap fst . listToMaybe . take 1
. dropWhile ((<= x) . snd)
. sortBy (comparing snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
This Maybe finds the index of the next smallest element in the list above the given element, situated after the given element, in the input list. As you've requested.
You can use any Enum type of your choosing as the index.
Now you can implement this higher-level executable specs as direct recursion, using an efficient Map data structure to hold your sorted elements above x seen so far to find the next smallest, etc.
Correctness first, efficiency later!
Efficiency update: dropping after the sort drops them sorted, so there's a wasted effort there; indeed it should be replaced with the filtering (as seen in the answer by Luis Morillo) before the sort. And if our element type is in Integral (so it is a properly discrete type, unlike just an Enum, thanks to #dfeuer for pointing this out!), there's one more opportunity for an opportunistic optimization: if we hit on a succ minimal element by pure chance, there's no further chance of improvement, and so we should bail out at that point right there:
bar :: (Integral a, Enum b) => a -> [a] -> Maybe b
bar x = fmap fst . either Just (listToMaybe . take 1
. sortBy (comparing snd))
. findOrFilter ((== succ x).snd) ((> x).snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
findOrFilter :: (a -> Bool) -> (a -> Bool) -> [a] -> Either a [a]
findOrFilter t p = go
where go [] = Right []
go (x:xs) | t x = Left x
| otherwise = fmap ([x | p x] ++) $ go xs
Testing:
> foo 5 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 4
> foo 2 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 1
> foo 1 [3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 9
im learning functional programming with Haskell and i have this exercise where i have something like [a], z, with [a] any kind of list and z the element that im gonna erase inside [a]. This problem it's kinda easy to solve (even for a newbie like me in Haskell) but I am having troubles with the way I need to print the output.
I need to create a tuple where the first element is the list without any z element and the number of times that it found z inside of a. Couple examples:
Input: [2,3,4,2,2] 2
Output: ([3,4],3)
Input: [1,1,1,1] 1
Output: ([],4)
Input: [1,2,3,4] 5
Output: ([1,2,3,4],0)
So far i've done something like this but I don't know how to keep going:
ex3 :: (Eq a, Num a) => [a] -> a -> ([a],Int)
ex3 [] _ = ([],0)
ex3 (x:xs) z | x == z = (xs,1) -- this line is wrong, but idk how to fix it
| otherwise = ([0],0) -- same here
I've done both problems individually (deleting z elements and counting how many times z is in [a]. Looks like this:
a) Deleting z elements:
ex3a :: (Eq a) => [a] -> a -> [a]
ex3a [] _ = []
ex3a (x:xs) z | x == z = ex3a xs z
| otherwise = x : ex3a xs z
b) Counting how many times z is in [a]:
ex3b :: (Eq a) => [a] -> a -> Int
ex3b [] _ = 0
ex3b (x:xs) z | x == z = 1 + ex3b xs z
| otherwise = ex3b xs z
Usually it helps to think of functions like in mathematics you think about inductive definitions. For example the first line of your function can read like:
"The ex3 of an empty list, and any element is a tuple containing the empty list and zero"
ex3 [] _ = ([], 0)
For non-empty lists of course the problem is a bit harder. Like in your code, there are basically two cases here.
"The ex3 of a non-empty list and an element z where the head of the list is not equal to z is the same as the ex3 of the tail of the list, but prepended with the head of that list", so we can write it like:
ex3 [] _ = ([], 0)
ex3 (x:xs) z | x /= z = (x:t, n)
| otherwise = ...
where (t, n) = ex3 xs z
So here we make a recursive call to ex3 with the tail of the list xs, and we obtain the result tuple (t, n), so t contains the "erased" tail, and n the number of times we removed the element, and in case x /= z, then we can return (x:t, n), since the number of removals does not change, but we have to prepend x to the list.
"The ex3 of a non-empty list and an element z where the head of the list is equal to z is the same as the ex3 of the tail of the list but with an incremented count", so:
ex3 :: (Eq a, Num n) => [a] -> a -> ([a], n)
ex3 [] _ = ([], 0)
ex3 (x:xs) z | x /= z = (x:t, n)
| otherwise = (t, n+1)
where (t, n) = ex3 xs z
We then obtain the expected results:
Prelude> ex3 [2,3,4,2,2] 2
([3,4],3)
Prelude> ex3 [1,1,1,1] 1
([],4)
Prelude> ex3 [1,2,3,4] 5
([1,2,3,4],0)
Just for fun, this is how I would implement that function:
import Data.Foldable
import Data.Monoid
ex3 :: Eq a => [a] -> a -> ([a], Int)
ex3 haystack needle = getSum <$> foldMap inject haystack where
inject hay | hay == needle = ([], 1)
| otherwise = ([hay], 0)
What I like about this is that the recursion pattern is immediately obvious -- at least to those familiar with Haskell's standard library -- without careful scrutiny (because it is just a call to foldMap).
The partition function consumes a predicate and a list; it produces a pair of lists whose first element satisfies the predicate, the second doesn't.
import Data.List (partition)
ex4 :: Eq a => [a] -> a -> ([a], Int)
ex4 xs x = length <$> partition (/= x) xs
I am trying to learn Haskell and I want to solve one task. I have a list of Integers and I need to add them to another list if they are bigger then both of their neighbors. For Example:
I have a starting list of [0,1,5,2,3,7,8,4] and I need to print out a list which is [5, 8]
This is the code I came up but it returns an empty list:
largest :: [Integer]->[Integer]
largest n
| head n > head (tail n) = head n : largest (tail n)
| otherwise = largest (tail n)
I would solve this as outlined by Thomas M. DuBuisson. Since we want the ends of the list to "count", we'll add negative infinities to each end before creating triples. The monoid-extras package provides a suitable type for this.
import Data.Monoid.Inf
pad :: [a] -> [NegInf a]
pad xs = [negInfty] ++ map negFinite xs ++ [negInfty]
triples :: [a] -> [(a, a, a)]
triples (x:rest#(y:z:_)) = (x,y,z) : triples rest
triples _ = []
isBig :: Ord a => (a,a,a) -> Bool
isBig (x,y,z) = y > x && y > z
scnd :: (a, b, c) -> b
scnd (a, b, c) = b
finites :: [Inf p a] -> [a]
finites xs = [x | Finite x <- xs]
largest :: Ord a => [a] -> [a]
largest = id
. finites
. map scnd
. filter isBig
. triples
. pad
It seems to be working appropriately; in ghci:
> largest [0,1,5,2,3,7,8,4]
[5,8]
> largest [10,1,10]
[10,10]
> largest [3]
[3]
> largest []
[]
You might also consider merging finites, map scnd, and filter isBig in a single list comprehension (then eliminating the definitions of finites, scnd, and isBig):
largest :: Ord a => [a] -> [a]
largest xs = [x | (a, b#(Finite x), c) <- triples (pad xs), a < b, c < b]
But I like the decomposed version better; the finites, scnd, and isBig functions may turn out to be useful elsewhere in your development, especially if you plan to build a few variants of this for different needs.
One thing you might try is lookahead. (Thomas M. DuBuisson suggested a different one that will also work if you handle the final one or two elements correctly.) Since it sounds like this is a problem you want to solve on your own as a learning exercise, I’ll write a skeleton that you can take as a starting-point if you want:
largest :: [Integer] -> [Integer]
largest [] = _
largest [x] = _ -- What should this return?
largest [x1,x2] | x1 > x2 = _
| x1 < x2 = _
| otherwise = _
largest [x1,x2,x3] | x2 > x1 && x2 > x3 = _
| x3 > x2 = _
| otherwise = _
largest (x1:x2:x3:xs) | x2 > x1 && x2 > x3 = _
| otherwise = _
We need the special case of [x1,x2,x3] in addition to (x1:x2:x3:[]) because, according to the clarification in your comment, largest [3,3,2] should return []. but largest [3,2] should return [3]. Therefore, the final three elements require special handling and cannot simply recurse on the final two.
If you also want the result to include the head of the list if it is greater than the second element, you’d make this a helper function and your largest would be something like largest (x1:x2:xs) = (if x1>x2 then [x1] else []) ++ largest' (x1:x2:xs). That is, you want some special handling for the first elements of the original list, which you don’t want to apply to all the sublists when you recurse.
As suggested in the comments, one approach would be to first group the list into tuples of length 3 using Preludes zip3 and tail:
*Main> let xs = [0,1,5,2,3,7,8,4]
*Main> zip3 xs (tail xs) (tail (tail xs))
[(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
Which is of type: [a] -> [b] -> [c] -> [(a, b, c)] and [a] -> [a] respectively.
Next you need to find a way to filter out the tuples where the middle element is bigger than the first and last element. One way would be to use Preludes filter function:
*Main> let xs = [(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
*Main> filter (\(a, b, c) -> b > a && b > c) xs
[(1,5,2),(7,8,4)]
Which is of type: (a -> Bool) -> [a] -> [a]. This filters out elements of a list based on a Boolean returned from the predicate passed.
Now for the final part, you need to extract the middle element from the filtered tuples above. You can do this easily with Preludes map function:
*Main> let xs = [(1,5,2),(7,8,4)]
*Main> map (\(_, x, _) -> x) xs
[5,8]
Which is of type: (a -> b) -> [a] -> [b]. This function maps elements from a list of type a to b.
The above code stitched together would look like this:
largest :: (Ord a) => [a] -> [a]
largest xs = map (\(_, x, _) -> x) $ filter (\(a, b, c) -> b > a && b > c) $ zip3 xs (tail xs) (tail (tail xs))
Note here I used typeclass Ord, since the above code needs to compare with > and <. It's fine to keep it as Integer here though.
So I have a problem where I need to see if a list of positions which are in the form of (x,y) are in increasing consecutive order.
Just a for an example of whats meant to happen
[(1,2), (1,3), (1,4), (1,5), (1,6)] it would return True, but
[(1,2), (1,3), (1,5), (1,6), (1,7)] will return False
For example starting off like this.
is_in_order :: [Position] -> Bool
Thanks for the help.
As this seems to be an exercise example I will only provide some hints and not a full solution:
for just checking if all second tuples are consecutive a simple
checkConsecutive :: Num a => [a] -> Bool
checkConsecutive x = and $ zipWith (\x y -> y - x == 1) x (drop 1 x)
but I guess the case at hand should be more general - your inOrder function already provides a good base line
isConsecutive :: Num a => [a] -> Bool
isConsecutive [] = True
isConsecutive [x] = True
isConsecutive (x:y:xs) = consecutive x y && isConsecutive (y:xs)
where consecutive :: (Num a, Num b) => (a,b) -> (a,b) -> Bool
consecutive (x1,y1) (x2,y2) = ..
You write that you need case in order to do that, you can use a case expression in consecutive, but I don't think it would make the function clearer.
Note: you can simplify the function above to
isConsecutive (x:y:xs) = consecutive x y && isConsecutive (y:xs)
where consecutive :: (Num a, Num b) => (a,b) -> (a,b) -> Bool
consecutive (x1,y1) (x2,y2) = ..
isConsecutive _ = True
the _ indicates a "catchall" pattern - i.e. it matches anything that is not matching the above patterns.
So the remaining task is to declare what it means for two tuples to be consecutive.
You can implement isInOrder this way:
isInOrder xs = all check $ zip xs $ tail xs where
check ((x1,y1),(x2,y2)) = x1<=x2 && y2-y1==1
You can modify check function the way you mean 'increasing consecutive order'
I've been trying to define a function which, given a list of Integers and an Integer n, returns a Boolean indicating whether n occurs exactly once in the list.
I have this, but it is not working and I cannot figure it out
once :: [a] -> (a -> Bool) -> Bool
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
An example of what I want would be:
Main> once [2,3,2,4] 2
False
Main> once [1..100] 2
True
As I thought my former solution was ugly, I asked in another forum and got this as answer:
once :: Eq a => a -> [a] -> Bool
once x = (== [x]) . filter (== x)
I think you can't write that function much nicer, and in contrast to the accepted answer it's lazy.
once :: (Eq a) => [a] -> a -> Bool
once xs x = (== 1) $ length $ filter (== x) xs
Well, you can filter the list, then see how many elements are in the resulting filter, right?
To get you started:
> filter (== 2) [1,2,3,4,5]
[2]
> filter (== 2) [1,2,3,4,5,2,2]
[2,2,2]
And to fold your list down to a Bool value, here, an example where we test if a list has three elements, returning a Bool:
> isThree (a:b:c:[]) = True
> isThree _ = False
So it is just a short matter of composing such functions:
> isThree . filter (==2)
or your variant (e.g. matching for lists of length 1).
Here is another version:
once x = not . (\xs -> null xs || x `elem` tail xs) . dropWhile (/= x)
--lambda hater version
import Control.Applicative
once x = not . ((||) <$> null <*> (elem x).tail) . dropWhile (/= x)
Of course it can't deal with infinite lists that contain zero or one x, but at least it terminates in case of more than one occurrence of x.