Haskell refer to list of list element - haskell

--This line count how many 0 are in the list
hasZero :: [Int] -> Bool
hasZero x = 0 < sum [1 | y <- x, y == 0]
--In this line I want to count how many empty list are in the list, but I got compiling erorr.
hasEmpty :: [[a]] -> Bool
hasEmpty x = 0 < [1 | y <- [x], y == []]

There are 2 issues in your second method - you are missing sum which does the count in the first one, and you are wrapping passed list into another one, it should be y <- x as in the first one:
hasEmpty :: [[a]] -> Bool
hasEmpty x = 0 < sum [1 | y <- x, null y]
Which can be rewritten as:
hasEmpty :: [[a]] -> Bool
hasEmpty = any null

In the first example, you summed the elements of the list your list comprehension generated. In the second, you haven't done this. You also don't need to put x in brackets.
hasEmpty :: Eq a => [[a]] -> Bool
hasEmpty x = 0 < sum [1 | y <- x, y == []]
This is a peculiar way to accomplish this goal. The more idiomatic way (aside from using the existing Prelude function any) would be to use pattern matching and recursion.
hasZero :: [Int] -> Bool
hasZero [] = True
hasZero (0:_) = True
hasZero (_:xs) = hasZero xs
Using any:
hasZero :: [Int] -> Bool
hasZero = any (== 0)

Related

Haskell: for every even appearance in an array, concatenate an int to the final list

I'm currently trying to write a function that takes as arguments an Int and an array of Ints and for every even value in the array, it concatenates the Int to the final array.
So, something like this:
f 3 [1,2,3,4,5,6] = [1,2,3,3,4,3,5,6,3]
This is the code I imagined would work (I'm just beginning so sorry if it's bad):
f :: Int -> [Int] -> [Int]
f(x,[]) = []
f(x,y)
|even head(y) = (head(y) ++ [x] ++ f(x,drop 1 y)
|otherwise = head(y) ++ f(x,(drop 1 y))
The error I'm getting is "Couldn't match expected type of 'Int' with actual type (a3, [[a3]])'. I understand the parameters types are mismatched, but I'm not sure how a proper syntax would look like here
You use (x, []), so that means the input type would be a tuple, so f :: (Int, [Int]) -> [Int].
I would also use pattern matching instead of head and tail, so:
f :: Int -> [Int] -> [Int]
f _ [] = []
f x (y:ys)
| even y = y : x : f x ys
| otherwise = y : f x ys
You can also generalize the type signature, and work with an inner function to avoid passing the x each time:
f :: Integral a => a -> [a] -> [a]
f x = go
where go [] = []
go (y:ys)
| even y = y : x : go ys
| otherwise = y : go ys
Another way of looking at this would be using a right fold to insert the desired element after even numbers.
f :: Int -> [Int] -> [Int]
f x lst = foldr (\y i -> if even y then y:x:i else y:i) [] lst
Which we can simplify to:
f :: Int -> [Int] -> [Int]
f x = foldr (\y i -> if even y then y:x:i else y:i) []
Note that without specifying the type, the more general inferred type of f would be:
f :: (Foldable t, Integral a) => a -> t a -> [a]

Cant match "Int -> Bool" with actual type "(Int,Bool)"

I'm writing a simple code to add numbers in the list with the correct conditions into a new list. But I'm getting an error that one of the input is (Int, Bool) instead of Int, how did this happen? Here's the code I'm writing
module FilterList where
-- Definisi dan Spesifikasi
countIf :: [Int] -> (Int,Bool) -> [Int]
{-Mencari elemen yang memenuhi kriteria tertentu-}
isPos :: Int -> Bool
{-True jika positif-}
isNeg :: Int -> Bool
{-True jika negatif-}
isKabisat :: Int -> Bool
{-True jika berada pada tahun kabisat (dapat dibagi 4 atau 400 tetapi tidak bisa dibagi 100)-}
isEmpty :: [Int] -> Bool
{-True jika list kosong-}
-- Realisasi
isEmpty li = (length li) == 0
isPos a = a >= 0
isNeg a = a < 0
isKabisat a = (mod a 4) == 0 && ((mod a 100) /= 0 || (mod a 400) == 0)
countIf li func
| isEmpty li = []
| func (head li) = [] ++ [head li] ++ countIf (tail li) func
| otherwise = [] ++ countIf (tail li) func
Some stuff are in Indonesian but only in the comments so the general idea is still there.
The signature is wrong: the func is a predicate, so:
countIf :: [Int] -> (Int -> Bool) -> [Int]
Your isEmpty function is however equivalent to null :: Foldable f => f a -> Bool (which is more efficient), and countIf is a special version of a "flipped" version of filter :: (a -> Bool) -> [a] -> [a]. The name countIf also suggests that you are counting the number of matched elements, not a list of items that match the predicate.
Using [] ++ xs makes not much sense: this will simply return the xs, and [x] ++ ys is equivalent to x : ys. You use pattern matching to avoid using head and tail, so:
countIf :: [a] -> (a -> Bool) -> [a]
countIf [] func = []
countIf (h:t) func
| func h = h : countIf t func
| otherwise = countIf t func
but countIf can thus be implemented as:
countIf :: [a] -> (a -> Bool) -> [a]
countIf = flip filter

Counting "perfect squares" in a list in Haskell

I am new to Haskell and I am struggling to get this concept to work.
I have to use a list of integers as a parameter and count the number of perfect squares (1,4,9,etc) in the list and output that value. So for example, if I entered myfunction[1,5,9] the output would be 2.
So far I have only got one function to work:
myfunction list = map per list
where per y = floor(sqrt (y) * sqrt (y))
Takes the square root of the element multiplied by the square root of the element. My mindset with the above is that I could set the above result equal to the original element. And if they are equal to each other, that would mean they are perfect squares. And then I would increment a value.
My issue is that my book doesn't give me any ideas for how to increment a variable or how to incorporate more than 1 function at a time. And as a result, I've been aimlessly working on this over the course of 3 days.
Thank you in advance for any help, advice, or resources!
fixing your version
first completed your version could look like this:
myfunction list = length $ filter per list
where
per y = floor(sqrt y * sqrt y) == y
this would even type-check but it would not work (try it)
that's because there is a small little problem - let's make it obvious by giving some types:
myfunction :: [Int] -> Int
myfunction list = length $ filter per list
where
per :: Int -> Bool
per y = floor(sqrt y * sqrt y) == y
you get an error:
No instance for (Floating Int) arising from a use of ‘sqrt’
it is trying to say to you that it does not know how to use sqrt for an Int - an easy fix is using fromIntegral and let it convert the Int into something that can:
myfunction :: [Int] -> Int
myfunction list = length $ filter per list
where
per :: Int -> Bool
per y = floor(sqrt (fromIntegral y) * sqrt (fromIntegral y)) == y
this kind of works (wrong answer) but gives an warning - we could get rid of with
myfunction :: [Int] -> Int
myfunction list = length $ filter per list
where
per :: Int -> Bool
per y = floor(sqrt (fromIntegral y :: Double) * sqrt (fromIntegral y)) == y
were we tell Haskell what type to use for the conversion (the warning would tell you that you default to this anyway).
So there is the wrong answer still.
#jpmarinier already told why - the way you test/sqr is sadly not cutting it (at least as I thought you wanted) - here is a fix:
myfunction :: [Int] -> Int
myfunction list = length $ filter per list
where
per :: Int -> Bool
per y = let y' = (fromIntegral y :: Double) in sqrt y' ** 2 == y'
where we first convert y to a Double value y' and test this.
Another option is using a integer-sqr as #jpmarinier mentioned:
myfunction :: [Int] -> Int
myfunction list = length $ filter per list
where
per :: Int -> Bool
per y = squareRoot y * squareRoot y == y
squareRoot :: Int -> Int
squareRoot = floor . sqrt . (fromIntegral :: Int -> Double)
that should finally work.
without floor and sqr:
ok this is maybe a bit to grok for you but here is how you can do this by sieving out the values.
Let's start by creating a (ascending) list of all perfect squares - I don't know which type you want those numbers to be so let's stay generic as well:
-- need later
import Data.List (sort)
perfectSquares :: Enum a => Num a => [a]
perfectSquares = [ n*n | n <- [1..] ]
no let's make a function counting elements from two lists - if the lists are sorted this can be done recursively by walking alongside the lists - I don't know if your input lists are always sorted so let's sort it before:
countOccurances :: (Enum a, Num a, Ord a) => [a] -> [a] -> a
countOccurances from list =
countAlong from $ sort list
where
countAlong [] _ = 0
countAlong _ [] = 0
countAlong allXs#(x:xs) allYs#(y:ys)
| x < y = countAlong xs allYs
| x > y = countAlong allXs ys
| otherwise = 1 + countAlong allXs ys
having both we can combine them for the answer:
import Data.List (sort)
countPerfectSquares :: (Enum a, Num a, Ord a) => [a] -> a
countPerfectSquares = countOccurances perfectSquares
countOccurances :: (Enum a, Num a, Ord a) => [a] -> [a] -> a
countOccurances from list =
countAlong from $ sort list
where
countAlong [] _ = 0
countAlong _ [] = 0
countAlong allXs#(x:xs) allYs#(y:ys)
| x < y = countAlong xs allYs
| x > y = countAlong allXs ys
| otherwise = 1 + countAlong allXs ys
perfectSquares :: Enum a => Num a => [a]
perfectSquares = [ n*n | n <- [1..] ]
Example:
> countPerfectSquares [1,5,9] :: Int
2

Assign the return value of two functions, to two variables, in a do block

Sorry for the title gore (if you can suggest a better, please do). But my problem is that I dont quite understand how to get this do block to work. I have a code that returns the position of 5 in a list of lists. Like such:
findFive :: [[Int]] -> (Int, Int)
findFive rs = do
x <- xPos rs 0
y <- yPos rs 0
return ( (x,y) )
xPos :: [[Int]] -> Int -> Int
xPos (rs:[[]]) n = n
xPos (rs:rss) n | elem 5 rs = n
| otherwise = xPos rss (n+1)
yPos :: [[Int]] -> Int -> Int
yPos (rs:[[]]) n = n
yPos (rs:rss) n | elem 5 rs = n
| otherwise = yPos rss (n+1)
I
But I cant use my do block this way. I can get it to work by doing
findFive :: [[Int]] -> (Int, Int)
findFive xs = ( (xPos xs 0), (yPos (transpose (xs)) 0) )
But that looks kinda ugly.
Also, is there a way to get this to work without sending in 0 to xPos and yPos ?
Why do? There are no monads there. A let..in suffices:
findFive :: [[Int]] -> (Int, Int)
findFive rs = let
x = xPos rs 0
y = yPos rs 0
in (x,y)
Alternatively, use where:
findFive :: [[Int]] -> (Int, Int)
findFive rs = (x, y)
where
x = xPos rs 0
y = yPos rs 0
You can't use a do block this way because in do blocks you have to (1) bind names to the 'contents' of monadic values, and (2) return a value wrapped in the same monadic type as used in (1). In this case the monadic type would be the list. It's appropriate to return a list of (row, column) pairs because that automatically handles both the cases of not finding the number, or finding it multiple times. So we could do something like
import Control.Monad
findFive ::
[[Int]] -> -- ^ a matrix of numbers.
[(Int, Int)] -- ^ the (zero-indexed) rows and columns of the number
-- ^ #5#, if any (otherwise empty list).
findFive xss =
do
(xs, rowIdx) <- xss `zip` [0 ..]
(x, colIdx) <- xs `zip` [0 ..]
guard $ x == 5
return (rowIdx, colIdx)
input :: [[Int]]
input = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
-- Should print "row: 1, col: 1".
main :: IO ()
main =
forM_ (findFive input) $ \(rowIdx, colIdx) ->
do
putStr "row: "
putStr $ show rowIdx
putStr ", col: "
print colIdx
Let's say pos is defined this way:
pos :: Eq => a -- A value to find
-> [[a]] -- A 2d matrix
-> Maybe Int -- Index of first row containing the value, if any
pos k rows = pos' rows 0
where pos' [] _ = Nothing
pos' (x:xs) n | elem k x = n
| otherwise = pos' xs (n+1)
There are several changes here:
It will work for lists of any type on which equality is defined, not just Int.
It is generalized to find any value k :: a, not just 5.
It can deal with failure to find any row containing k.
With this definition, we could define findFive as
findFive :: [[Int]] -> (Maybe Int, Maybe Int)
findFive xs = (pos 5 xs, pos 5 (transpose xs))
Using Control.Lens, you can factor out the function pos 5 so that it only needs to be written once. Think of over both as a version of map for pairs instead of lists.
import Control.Lens
findFive xs = over both (pos 5) (xs, transpose xs)
Using Control.Arrow, you can factor out the argument xs so that it only needs to be written once.
import Control.Lens
import Control.Arrow
findFive xs = over both (pos 5) ((id &&& transpose) xs)
-- id &&& transpose = \x -> (id x, transpose x)
Once you've done that, you can easily write findFive in point-free style, by composing over both (pos 5) and id &&& transpose:
findFive = over both (pos 5) . (id &&& transpose)

How do I put a element n times in a list without using the replicate or repeat function?

I have a function rep which requires a list with ints. My task now is to put each of these numbers in separate lists with n times the number. For example
[1,3,5] to [[1],[3,3,3],[5,5,5,5,5]] So far I can put each int in a separate list but I don't really now how to put them n times in the list without using replicate or repeat.
This is the code I have so far:
rep [] = []
rep (x1:xs) = [[x1]] ++ (rep xs)
As this is a homework/learning exercise - just want to give some hints
Split the task in two parts a function
myReplicate :: Int -> a -> [a] which replicates a single element as many times as the Int tells it to.
myReplicate n x | n > 0 = ...
| n == 0 = ...
| n < 0 = error "Error myReplicate: no negative arguments allowed"
a second function myMap :: (a -> b) -> [a] -> [b] that applies a function to every element of a given list.
myMap :: (a -> b) -> [a] -> [b]
myMap f [] = []
myMap f (x:xs) = ...
then rep = myMap (\x -> myReplicate x x)
Here a solution without repeat or replicate:
rep = map (\ n -> foldr (const (n :)) [] [1..n])

Resources