find a Float value not over another value haskell - haskell

I have to find a height that's not taller than a given value. I have found code that does it for a list of integers. But I need it to accept a float value i.e. countElems :: Float -> Heights -> Int. I know I have to use fromIntegral to allow a Float value but I don't know how to implement it. This is what I have so far:
countElems :: Int -> [Int] -> Int
countElems n (x:xs) = fromEnum (n < x) + countElems n xs
countElems _ [] = 0

Just edit countElems type annotation to accept any ordered type:
countElems :: Ord a => a -> [a] -> Int
countElems n (x:xs) = fromEnum (n < x) + countElems n xs
countElems _ [] = 0
Now it works both for Int and Float and for every instance of Ord type class.
Actually, it's an actual type of countElems which compiler infers. Your version is restricted only for a = Float.

I got it to work using:
countElems :: Float -> [Float] -> Int
countElems _ [] = 0
countElems n (x:xs)
| n < x = 1 + (tallerthan n xs)
| otherwise = tallerthan n xs

Related

How can I make this code to work with the Integer- > Int type signature?

This code is working with the Int- > [Int] type signature, but I have to solve it with Integer -> [Int] type signature. What do I have to change to make it work?
toBin :: Int -> [Int]
toBin n
| n == 0 = []
toBin n = [n `mod` 2] ++ toBin (n `div` 2)
You can use fromIntegral :: (Integral a, Num b) => a -> b to convert an Integer (or any Integral type) to an Int (or any Num type):
toBin :: Integer -> [Int]
toBin 0 = []
toBin n = [fromIntegral (n `mod` 2)] ++ toBin (n `div` 2)
If n is an Integer, than n `mod` `2 is an Integer as well. We can not use n `mod` 2 as element of a list, since the return type is [Int], so a list of Ints. We thus need to convert the Integer to an Int such that the type of the elements is correct, and we can convert an Integer to the corresponding Int (given the Integer can be represented by an Int) with fromIntegral.

Output of a list of Maybe Int with Just in every element in Haskell

I have this function which takes an integer n and returns a list of type Maybe Int, containing the unique prime factors. I don't understand why it returns them with Just inside every element of the list.
I expect an output like this:
primeFactors 75 = Just [3,5]
But I have one that looks like this:
primeFactor 75 = [Just 5,Just 3,Just 1]
Here is my code:
divides :: Int -> Int -> Bool
divides m n = rem m n == 0
transform :: Int -> Int
transform n = (n*2) + 1
isComposite :: Int -> Bool
isComposite n = foldl (||) (divides n 2) (map (divides n) (map (transform) [1..(div n 4)]))
isPrime :: Int -> Bool
isPrime n
| n <= 0 = error "Makes no sense"
| n < 4 = True
| otherwise = not (isComposite n)
primeFactors :: Int -> [Maybe Int]
primeFactors 0 = [Nothing]
primeFactors n = primeFactors2 n ((div n 2)+1)
primeFactors2 :: Int -> Int -> [Maybe Int]
primeFactors2 n 0 = []
primeFactors2 n x
| divides n x && isPrime x = Just x:primeFactors2 n (x-1)
| otherwise = primeFactors2 n (x-1)
Here is a version of your code that I think will do what you want:
primeFactors :: Int -> Maybe [Int]
primeFactors n
| n <= 0 = Nothing
| otherwise = Just $ primeFactors2 n n
primeFactors2 :: Int -> Int -> [Int]
primeFactors2 n p
| n <= 1 || p <= 1 = []
| divides n p && isPrime p = p : primeFactors2 (n `div` p) p
| otherwise = primeFactors2 n (p-1)
isPrime :: Int -> Bool
isPrime n
| n <= 1 = False
| otherwise = not (isComposite n)
isComposite :: Int -> Bool
isComposite n =
any (divides n) [2..n-1]
divides :: Int -> Int -> Bool
divides m n =
rem m n == 0
Please note that (for clarity's sake I hope) I did remove some of your optimizations and made a major change: this one will report Just [2,2] as prime-factors for 4
(IMO you want product <$> primeFactors n == Just n).
If not (as your example indicates) it shouldn't be too hard to fix this (just take your version).
Anyway the only really interesting contribution is how primeFactor handles primeFactors2 to get you the Maybe result.

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

length of list using foldr in haskell

I wrote the following code to calculate length of a list using foldr in haskell. When I compile the code it gives me error as "myfoldr.hs:3:1: parse error on input `where'". Can anyone please tell me what thing I might be missing or doing wrong in this code ?
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where
f :: Int -> Int -> Int
f x y = y+1
In Haskell, whitespace matters - look at the guide on the Haskell wiki.
Formatting your code more correctly gives:
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where
f :: Int -> Int -> Int
f x y = y + 1
Which works perfectly (although the argument x to f is a bit redundant, you might want to write it as f _ y = y + 1 instead, or use a lambda expression like foldr (\_ x -> x + 1) 0 l).
This is an indentation error: you have to indent the where clause, since otherwise Haskell will see the definition of f as a separate function. So we can fix it with:
mylength :: [Int] -> Int
mylength l = foldr f 0 l
where f :: Int -> Int -> Int
f x y = y+1
Nevertheless we can still make it more generic: instead of defining it for an [Int] list, we can define it over an [a] list, with:
mylength :: [a] -> Int
mylength l = foldr f 0 l
where f x y = y+1
We can also rewrite f as const (+1), so:
mylength :: Num n => [a] -> n
mylength = foldr (const (1+)) 0
Note that we can apply an eta-reduction here: remove l both in the head and the body of the mylength definition. Or in case we know that the number is also enumerable, we can use succ instead of (1+):
mylength :: (Enum n, Num n) => [a] -> n
mylength = foldr (const succ) 0

Int -> Integer: type conversation misunderstanding

Here is my code for the calculating fibonacci numbers:
f' :: (Int -> Int) -> Int -> Int
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)
f'_list :: [Int]
f'_list = map (f' faster_f') [0..]
faster_f' :: Int -> Int
faster_f' n = f'_list !! n
It works fine while 'n' is small. To resolve the problem with big numbers I would like convert Int-type to Integer:
f' :: (Integer -> Integer) -> Integer -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)
f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]
faster_f' :: Integer -> Integer
faster_f' n = f'_list !! n
With this code I get the error:
Couldn't match expected type `Int' with actual type `Integer'
In the second argument of `(!!)', namely `n'
In the expression: f'_list !! n
In an equation for `faster_f'': faster_f' n = f'_list !! n
Well, I have understood correctly the index of element in the list can not be Integer-type.
OK:
f' :: (Integer -> Integer) -> Integer -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)
f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]
faster_f' :: **Int** -> Integer
faster_f' n = f'_list !! n
But now I get the error:
Couldn't match expected type Integer' with actual typeInt'
Expected type: Integer -> Integer
Actual type: Int -> Integer
In the first argument of `f'', namely `faster_f''
In the first argument of `map', namely `(f' faster_f')'
Why? And how can I fix it?
The easiest way is to make your arguments Int (as they are indexes of Fibonacci numbers, not the numbers themselve), and use Integer just for the output:
f' :: (Int -> Integer) -> Int -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)
f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]
faster_f' :: Int -> Integer
faster_f' n = f'_list !! n
Of course now you can't address Fibonacci numbers with an index outside the Int range, but practically you'll run out of space and time much, much, much sooner.
By the way, if you need a list of fibs, the "usual" implementation is
fibs :: [Integer]
fibs = 0 : scanl (+) 1 fibs
If you need just certain values, there is a fast calculation method similar to fast exponentiation using these formulas:
f(2n) = (2*f(n-1) + f(n)) * f(n)
f(2n-1) = f(n)² + f(n-1)²
Why?
Because f' expects an Integer -> Integer function, but you're sending it faster_f', which is an Int -> Integer function.
And how can I fix it?
Probably the easiest way is to use genericIndex (from Data.List) instead of (!!).
Integer is the infinite type of Int, (Int is only guaranteed to cover the range from -2^29 to 2^29-1, but in most implementations it's the full 32 or 64-bit type). That's why you get the first error. The second error you get because (!!) is a function that takes an list and an Int
(!!) :: [a] -> Int -> a
There are a lot of other (and maybe easier) ways to calculate the Fibonacci numbers. Here is one example that returns a list of all Fibonacci numbers to the specified. The first call is done by fibCall
fib :: Integer -> Integer -> Integer -> [Integer] -> [Integer]
fib 0 _ _ l = l
fib n a b l = fib (n-1) b (a+b) (a:l)
fibCall :: Integer -> [Integer]
fibCall n = n 1 1 []
If you just want the nth Fibonacci number, change [Integer] to Integer and (a:l) to a.

Resources