non-exhaustive pattern matches on list of tuples [duplicate] - haskell

This question already has answers here:
Non exhaustive pattern in function noThirds
(3 answers)
Closed 5 years ago.
I'm not sure what I'm missing here, but I have been unable to get the pattern matching on checkDiff to work in the code below. GHCi report "non-exhaustive patterns in function checkDiff. The code is:
import Data.Array.Unboxed
primes :: [Int]
primes = 2 : oddprimes ()
where
oddprimes () = 3 : sieve (oddprimes ()) 3 []
sieve (p:ps) x fs = [i*2 + x | (i,True) <- assocs a]
++ sieve ps (p*p) ((p,0) :
[(s, rem (y-q) s) | (s,y) <- fs])
where
q = (p*p-x)`div`2
a :: UArray Int Bool
a = accumArray (\ b c -> False) True (1,q-1)
[(i,()) | (s,y) <- fs, i <- [y+s, y+s+s..q]]
takePrimes :: [Int] -> [(Int,Int)]
takePrimes [] = []
takePrimes [x] = []
takePrimes (x:y:zs) = if y - x > 2 then (x,y) : takePrimes (y:zs) else takePrimes (y:zs)
checkDiff :: [(Int,Int)] -> Int
checkDiff [] = 0
checkDiff [(0,_)] = 0
checkDiff [(_,0)] = 0
checkDiff [(a,b)] = sum $ [x | x <- [(a + 1)..(b - 1)], totalFactors a == totalFactors (a + 1)]
totalFactors :: Int -> Int
totalFactors n = length $ [x | x <- [2..(div n 2)], rem n x == 0]
Please help.

checkDiff only handles lists of length zero and one. It is probably called with a longer list, triggering the non-exhaustiveness error.
You should turn on warnings with the -Wall flag. If you do, GHC will report such problems at compile time instead.

Related

How can i solve this in haskell? [duplicate]

This question already has answers here:
Better exception for non-exhaustive patterns in case
(2 answers)
Closed 4 years ago.
I got this code to make a transposed matrix, but it doesn't work 100% fine.
type Mat a = [[a]]
transpose' :: Eq a => Mat a -> Mat a
transpose' [] = []
transpose' (h:t) = primelem (h:t):transpose' (eliminate' (h:t))
primelem :: Mat a -> [a]
primelem [] = []
primelem [[x]] = [x]
primelem ((x:xs):t) = x : primelem t
eliminate' :: Eq a => Mat a -> Mat a
eliminate' [] = []
eliminate' (h:t) = (delete (head h) h):eliminate' t
*Main> transpose' [[1,2,3],[0,4,5],[0,06]]
[[1,0,0],[2,4,6],[3,5*** Exception:(..)Non-exhaustive patterns in function primelem
I am trying to figure it out, but i really don't know which case is missing.
To discover which cases you are missing, you should turn on warnings using the -Wall flag, as shown in the GHCi session below.
> :set -Wall
> type Mat a = [[a]]
> :{
| primelem :: Mat a -> [a]
| primelem [] = []
| primelem [[x]] = [x]
| primelem ((x:xs):t) = x : primelem t
| :}
<interactive>:5:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘primelem’: Patterns not matched: ([]:_)
<interactive>:7:14: warning: [-Wunused-matches]
Defined but not used: ‘xs’
So, the case you are missing is:
primelem ([]:t) = ...
You're over-thinking this. A list of empty lists is its own transpose.
transpose m | all null m = []
| any null m = error "Not a matrix"
Otherwise, take the first element of each list as the first row of the transpose, and transpose the remaining matrix as the rest of the transpose.
transpose m = map head m : transpose (map tail m)
This function is effectively total, failing only on those lists-of-lists that aren't actually matrices. The fact that it fails late on non-matrix values is a bit of a wart:
> transpose [[1,2], [3]]
[[1,3]*** Exception: Not a matrix
CallStack (from HasCallStack):
error, called at tmp.hs:3:28 in main:Main
If you want to handle invalid matrices a little more cleanly, return a Maybe (Mat a) instead.
transpose :: Mat a -> Maybe (Mat a)
transpose m | all null m = Just []
| any null m = Nothing
| otherwise = ((map head m):) <$> transpose (map tail m)

Create a list of divisible integers in haskell

I'm new to haskell and I'm trying to create an expression, that gives a list of integers from 0 to n, which are divisible by 3. The script I wrote doesn't work and I'm not sure for what reason.
zeroto :: Int -> [Int]
zeroto n = [x | x <- [0..n]]
where
x "mod" 3 == 0
where doesn't work like that. It's not a filter -- it's locally-scoped definitions.
However, a list comprehension does allow for filters, you've just not put it in the right place.
zeroto :: Int -> [Int]
zeroto n = [x | x <- [0..n], x `mod` 3 == 0]
Alternatively, you could define a filter function in the where block and filter afterwards, but this is kind of silly.
zeroto :: Int -> [Int]
zeroto n = divisibleByThree [0..n]
where divisibleByThree = filter (\x -> x `mod` 3 == 0)
This is not the best way but using simple recursion it can be done as
mod3Arr :: Int -> [Int]
mod3Arr 0 = [0]
mod3Arr n | nmod3 == 0 = smallerArr ++ [n]
| otherwise = smallerArr
where smallerArr = mod3Arr ( n - 1)

How can I return a list from list of list Haskell

Basically, I have a function which checks every permutation of [1..9] by several conditions. Plus I have a function which checks if the sum of the list is equal to a number and a function which slice the list. The problem is that it returns an error Couldn't match type 'Int' with 'Char'. It points on the list which function has to return if all conditions are true.
Here is the code itself :
intSumList :: Int -> [Int] -> Bool
intSumList _ [] = True
intSumList x (y:ys)
| x == sum (y:ys) = True
| otherwise = False
slice :: Int -> Int -> [Int] -> [Int]
slice from to s = take (to - from + 1)(drop from s)
find :: (Int,Int,Int,Int) -> [Int]
find (x,z,y,s) = checkPerm (x,z,y,s) l
where
l = L.permutations [1..9]
checkPerm (_,_,_,_ ) [] = ""
checkPerm (x,z,y,s) (p:pz)
| intSumList x (slice 1 5 p) && intSumList z (slice 2 6 p) &&
intSumList y (slice 4 8 p) && intSumList s (slice 5 9 p) = p
| otherwise = permutations (x,z,y,s) pz
Your immediate problem is that checkPerm is returning an empty list of type [Char], not [Int], when it gets an empty list as its second argument.
However, checkPerm is basically reimplementing Data.List.find.
import qualified Data.List as DL
import Data.Maybe
import Control.Monad
find :: (Int,Int,Int,Int) -> [Int]
find (x,z,y,s) = fromMaybe [] (DL.find p l)
where makePred x lo hi p = intSumList x (slice lo hi p)
p1 = makePred x 1 5
p2 = makePred z 2 6
p3 = makePred y 4 8
p4 = makePred s 5 9
p = liftM4 (&&) p1 p2 p3 p4
l = DL.permutations [1..9]
DL.find returns Nothing if no match is found, or Just l for a a matching list l. fromMaybe converts this value to either an empty list or the found list. You might consider leaving the return value of find as Maybe [Int] instead, though.

counting frequencies in a collection of bins

I need to count values inbetween values in a list i.e. [135,136,138,140] would count all the numbers between 135-136,136-138,138-140. with the input list [135.2,135.3,137,139] would out put[2,1,1] using type [Float] [Float] [Int]. So far I have:
heightbetween :: Float -> Float -> [Float] -> Int
heightbetween _ _ [] = 0
heightbetween n s (x:xs)
| (n < x) && (s > x) = 1 + (heightbetween n s xs)
| otherwise = heightbetween n s xs
count :: [Float] -> [Float] -> [Int]
count [] [] = []
count [x,y] = [(x,y)]
count (x:y:ys) = (x,y):count (y:ys)
forEach fun lst = heightbetween op ([],lst)
where
op (start,[]) = Nothing
op (start,a:as) = Just (start++(fun a):as
,(start++[a],as))
forPairs fun lst lst2 = map (map fst)
$ forEach (\(a,b)->(fun a b,b))
$ zip lst lst2
Your count looks strange. It should be like this:
-- count -> ranges -> data -> [counts]
count :: [Float] -> [Float] -> [Int]
count [] _ = [] -- no ranges given -> empty list
count [_] _ = [] -- no ranges, but single number -> empty list
count _ [] = [] -- no data given -> empty list
count (x:y:xs) d =
(heightbetween x y d) : count (y:xs) d
heightbetween :: Float -> Float -> [Float] -> Int
heightbetween _ _ [] = 0
heightbetween n s (x:xs)
| (n < x) && (s > x) = 1 + (heightbetween n s xs)
| otherwise = heightbetween n s xs
The other lines are obsolete.
Then invoking
count [135,136,138,140] [135.2,135.3,137,139]
gives
[2,1,1]
First, make sure that your range list is in order....
rangePoints = [135,136,138,140]
orderedRangePoints = sort rangePoints
Next, you will find it much easier to work with actual ranges (which you can represent using a 2-tuple (low,high))
ranges = zip orderedRangePoints $ tail orderedRangePoints
You will need an inRange function (one already exists in Data.Ix, but unfortunately it includes the upperbound, so you can't use it)
inRange (low,high) val | val >= low && val < high = True
inRange _ _ = False
You will also want to order your input points
theData = sort [135.2,135.3,137,139]
With all of this out of the way, the binCount function is easy to write.
binCount'::[(Float, Float)]->[Float]->[Int]
binCount' [] [] = []
binCount' (range:rest) vals =
length valsInRange:binCount' rest valsAboveRange
where
(valsInRange, valsAboveRange) = span (`inRange` range) vals
Notice, that I defined a function called binCount', not binCount. I did this, because I consider this an unsafe function, because it only works on ordered ranges and values.... You should finalize this by writing a safer binCount function, which puts all of the stuff above in its where clause. You should probably add all the types and some error checking also (what happens if a value is outside of all ranges?).

Comparing 3 output lists in haskell

I am doing another Project Euler problem and I need to find when the result of these 3 lists is equal (we are given 40755 as the first time they are equal, I need to find the next:
hexag n = [ n*(2*n-1) | n <- [40755..]]
penta n = [ n*(3*n-1)/2 | n <- [40755..]]
trian n = [ n*(n+1)/2 | n <- [40755..]]
I tried adding in the other lists as predicates of the first list, but that didn't work:
hexag n = [ n*(2*n-1) | n <- [40755..], penta n == n, trian n == n]
I am stuck as to where to to go from here.
I tried graphing the function and even calculus but to no avail, so I must resort to a Haskell solution.
Your functions are weird. They get n and then ignore it?
You also have a confusion between function's inputs and outputs. The 40755th hexagonal number is 3321899295, not 40755.
If you really want a spoiler to the problem (but doesn't that miss the point?):
binarySearch :: Integral a => (a -> Bool) -> a -> a -> a
binarySearch func low high
| low == high = low
| func mid = search low mid
| otherwise = search (mid + 1) high
where
search = binarySearch func
mid = (low+high) `div` 2
infiniteBinarySearch :: Integral a => (a -> Bool) -> a
infiniteBinarySearch func =
binarySearch func ((lim+1) `div` 2) lim
where
lim = head . filter func . lims $ 0
lims x = x:lims (2*x+1)
inIncreasingSerie :: (Ord a, Integral i) => (i -> a) -> a -> Bool
inIncreasingSerie func val =
val == func (infiniteBinarySearch ((>= val) . func))
figureNum :: Integer -> Integer -> Integer
figureNum shape index = (index*((shape-2)*index+4-shape)) `div` 2
main :: IO ()
main =
print . head . filter r $ map (figureNum 6) [144..]
where
r x = inIncreasingSerie (figureNum 5) x && inIncreasingSerie (figureNum 3) x
Here's a simple, direct answer to exactly the question you gave:
*Main> take 1 $ filter (\(x,y,z) -> (x == y) && (y == z)) $ zip3 [1,2,3] [4,2,6] [8,2,9]
[(2,2,2)]
Of course, yairchu's answer might be more useful in actually solving the Euler question :)
There's at least a couple ways you can do this.
You could look at the first item, and compare the rest of the items to it:
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [4,5,6] ]
False
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [1,2,3] ]
True
Or you could make an explicitly recursive function similar to the previous:
-- test.hs
f [] = True
f (x:xs) = f' x xs where
f' orig (y:ys) = if orig == y then f' orig ys else False
f' _ [] = True
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> f [ [1,2,3], [1,2,3], [1,2,3] ]
True
*Main> f [ [1,2,3], [1,2,3], [4,5,6] ]
False
You could also do a takeWhile and compare the length of the returned list, but that would be neither efficient nor typically Haskell.
Oops, just saw that didn't answer your question at all. Marking this as CW in case anyone stumbles upon your question via Google.
The easiest way is to respecify your problem slightly
Rather than deal with three lists (note the removal of the superfluous n argument):
hexag = [ n*(2*n-1) | n <- [40755..]]
penta = [ n*(3*n-1)/2 | n <- [40755..]]
trian = [ n*(n+1)/2 | n <- [40755..]]
You could, for instance generate one list:
matches :: [Int]
matches = matches' 40755
matches' :: Int -> [Int]
matches' n
| hex == pen && pen == tri = n : matches (n + 1)
| otherwise = matches (n + 1) where
hex = n*(2*n-1)
pen = n*(3*n-1)/2
tri = n*(n+1)/2
Now, you could then try to optimize this for performance by noticing recurrences. For instance when computing the next match at (n + 1):
(n+1)*(n+2)/2 - n*(n+1)/2 = n + 1
so you could just add (n + 1) to the previous tri to obtain the new tri value.
Similar algebraic simplifications can be applied to the other two functions, and you can carry all of them in accumulating parameters to the function matches'.
That said, there are more efficient ways to tackle this problem.

Resources