Having Trouble with tuples in Haskell - list

i have this function:
pairs :: [a] -> [(a,a)]
pairs xs = zip xs (tail xs)
and i have to write another one, based on Pairs, that returns True if at least one pair of tuples is in an ascending order (e.g (2,3)).
here's my attempt at this:
unsorted :: Ord a => [a] -> Bool
unsorted xs = [if fst x < snd x then True else False| x <- pairs xs]
why is this wrong ?

Your function returns a list of Bools, not a Bool. You can use any:
unsorted xs = any (\x -> fst x < snd x) xs
or
unsorted = any (\(x, y) -> x < y)
if you want to use a list comprehension you can add a filter and then see if the resulting list contains any elements:
(length [x | x <- pairs xs, fst x < snd x]) > 0
or
(length [x | (x,y) <- pairs xs, x < y]) > 0

Looking at the type error that GHC gives you should give you a hint about what the error is.
Couldn't match expected type `Bool' with actual type `[Bool]'
Your signature indicates that you want to a return a Bool but your implementation yields a list of Bools. To fix this use the function ( any :: (a -> Bool) -> [a] -> Bool ):
unsorted :: Ord a => [(a, a)] -> Bool
unsorted xs = any (\(a,b) -> a < b) xs

Related

Sorting lists in list by length using bubble sort - Haskell

I have an input, which is of type [[a]] and I am trying to sort the lists in the list by their length. I am working on my own implementation of bubble sort, which currently looks like this:
myInput :: Ord a => [[a]] -> [[a]]
myInput [[]] = [[]]
myInput [[x]] = [[x]]
myInput (x : xs) = mySort x (myInput xs)
mySort :: Ord a => [a] -> [[a]] -> [[a]]
mySort x [[]] = [x]
mySort x (y:ys) | (length x) < (length y) = x:y:ys
| otherwise = y:(myInput x ys)
However, when I input myInput[[1,2],[1]], I get a non-exhaustive pattern error:
[[1]*** Exception: CourseworkRev.hs:(197,1)-(200,49): Non-exhaustive patterns in function myInput
I am probably doing something wrong when declaring the empty lists, as this is a recursion error (correct me if I am wrong). Any tips on how to make this working? Thanks!
myInput has no pattern for an empty list, only for a list with one element that is an empty list. You likely do not need patterns like [[]] and [[x]] anyway, since for a list with a single element, you will return a list with that element, regardless of it length, so:
myInput :: Ord a => [[a]] -> [[a]]
myInput [] = []
myInput [x] = [x]
myInput (x : xs) = mySort x (myInput xs)
[[x]] matches with a list that contains exactly one sublist [x] which is a list with one element. So this will match with [[1]], but not with [[1,2]]. [x] on the other hand matches with any singleton list: a list with one element so [[1]], [[1,4]], [[1,4,2,5]], and [[]] will all match.

F# Transforming function into using higher-order functions

I have this series of functions, isMember, addElem and countries:
let rec isMember x = function
| y::ys -> y=x || (isMember x ys)
| [] -> false
let addElem x ys = if isMember x ys then ys else x::ys
let rec countries = function
| [] -> []
| (c1,c2)::m -> addElem c1 (addElem c2 (countries m))
I want to rewrite countries using higher-order functions, but I'm not entirely sure how to:
My guess would be it having something to do with List.map, as I'm applying a function to each element of the list.
let countriesHigherOrder m =
List.map (fun x -> addElem x m)
Instead of using List.map, you can use List.fold with an accu that you initialize to [] and add elements to accu.
let countriesHigherOrder m =
List.fold (fun acc (c1,c2) -> addElem c1 (addElem c2 acc)) [] m
or by defining addPair:
let addPair (x, y) ys =
addElem x (addElem y ys)
let countriesHigherOrder m =
List.fold (fun acc (c1,c2) -> addPair (c1, c2) acc) [] m
If you want to flatten a list of pairs into a simple list and at the same time, preserve only one occurence of identical elements, the shortest code will involve the append operator.
let countries' m =
List.unzip m ||> (#)
|> Seq.distinct
|> Seq.toList
If, on the other hand, you need the peculiar order of your doubly recursive approach, you can convert the list of tuples into two-element lists and concatenate those.
let countries'' m =
List.rev m
|> List.collect(fun (x,y) -> [y;x])
|> Seq.distinct
|> Seq.toList
|> List.rev

predicate and a list search haskell

I am learning Haskell at the moment and have come to a bit of a standstill. I'm trying to write a function that takes a predicate p and a list xs and returns the list of those elements of xs which immediately follow an element which passes the predicate p. Here is what I have :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter x (y:ys) =
if x y
then (map head [ys])
else
afterFilter x (tail ys)
test input : afterFilter (<0) [-4,7,-4,-8,3,-3,-6,0,-9,-1]
output : [7]
The trick is to pull two elements out of the input list by pattern-matching two cons cells. If the first element passes the predicate, we stick the second on the output. But don't forget to stick the second element back on the input list when you make the recursive call.
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter f [] = [] -- input list is empty
afterFilter f [x] = [] -- input list has only one element - no "next element" to return
afterFilter f (x:y:xs) =
let ys = afterFilter f (y:xs)
in (if f x then y:ys else rest)
However, a higher-level - and much more Haskellish - way to approach the problem would be to break it down into a pipeline of operations.
Pair up each item in the list with the element that follows it using zip, so we have a list of (element, next) pairs.
Use filter to drop the pairs for which element does not pass the predicate.
Use map to extract the next part of each surviving pair.
So the code looks like this:
pairWithSuccessors :: [a] -> [(a, a)]
pairWithSuccessors xs = zip xs (tail xs)
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p xs =
let withSuccessors = pairWithSuccessors xs (tail xs)
filtered = filter (\(element, next) -> p element) withSuccessors
filteredSuccessors = map (\(element, next) -> next) filtered
in filteredSuccessors
Or, written in point-free style:
afterFilter p = map snd . filter (p . fst) . pairWithSuccessors
Functions built with the composition operator . are read right-to-left: first pairWithSuccessors, then filter (p . fst), then map snd over the result.
GHC is good at working with lists: when compiled with optimisations, both approaches should produce roughly the same machine code - that is, there's no performance cost to the high-level solution
Following what you did, there are some strange things with your code :
The map head [ys] is very odd, and causes your function to stop : At the first element matching the predicate, your function returns a list containing its immediate successor and stops there. You still need to process the rest of the list.
Also, following your definition of the problem, each item which is a successor of an item passing the predicate should be on the resulting array. I may be wrong, but what I understood is that afterFilter (<0) [-1, -1, 1] should return [-1, 1].
However, you're discarding one element you didn't check for by calling tail ys : You checked for y, but not for head ys.
Finally, by adding the edge cases, here is what you get :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter _ [] = []
afterFilter _ [_] = []
afterFilter x (y:ys#(z:zs)) =
if x y
then z : afterFilter x ys
else
afterFilter x ys
Try:
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p [] = []
afterFilter p [_] = []
afterFilter p (x1:x2:xs)
| p x1 = x2:rest
| otherwise = rest
where rest = afterFilter p (x2:xs)
Or
afterFilter' :: (a -> Bool) -> [a] -> [a]
afterFilter' p xs = map snd $ filter (\(x, _) -> p x) $ zip xs (tail xs)
Or
afterFilter'' :: (a -> Bool) -> [a] -> [a]
afterFilter'' p xs = [y | (x, y) <- zip xs (tail xs), p x]

haskell, is number in one list is within the range of a second list?

What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]

How to compute frequency via list comprehension?

count :: Eq a => a -> [a] -> Int
count n [] = 0
count n (x:xs) | n == x = 1 + count n xs
| otherwise = count n xs
rmdups :: Eq a => [a] -> [a]
rmdups [ ] = [ ]
rmdups (x:xs) = x : rmdups (filter(/= x) xs)
using the 2 functions, a third needs to be created, called frequency:
it should count how many times each distinct value in a list occurs in that list. for example : frequency "ababc", should return [(3,'a'),(2,'b'),(1,'c')].
the layout for frequency is :
frequency :: Eq a => [a] -> [(Int, a)]
P.s rmdups, removes duplicates from list, so rmdups "aaabc" = abc
and count 2 [1,2,2,2,3] = 3.
so far i have:
frequency :: Eq a => [a] -> [(Int, a)]
frequency [] = []
frequency (x:xs) = (count x:xs, x) : frequency (rmdups xs)
but this is partly there, (wrong). thanks
frequency xs = map (\c -> (count c xs,c)) (rmdups xs)
or, with a list comprehension,
frequency xs = [(count c xs, c) | c <- rmdups xs]
is the shortest way to define it using your count and rmdups. If you need it sorted according to frequency (descending) as in your example,
frequency xs = sortBy (flip $ comparing fst) $ map (\c -> (count c xs,c)) (rmdups xs)
using sortBy from Data.List and comparing from Data.Ord.
If all you have is an Eq constraint, you cannot gain much efficiency, but if you only need it for types in Ord, you can get a much more efficient implementation using e.g. Data.Set or Data.Map.
Here is my own 'lazy' answer, which does not call rmdups:
frequency [] = []
frequency (y:ys) = [(count y (y:ys), y)] ++ frequency (filter (/= y) ys)
import qualified Data.Set as Set
frequency xs = map (\x -> (length $ filter (== x) xs, x)) (Set.toList $ Set.fromList xs)