Haskell Beginner problems, list comprehension with single input - haskell

I am brand new to haskell and functional programming in general.
How can I create a function that finds all odd numbers less than 200 that are divisible by 3 and 7 using only list comprehension?
this is my code:
oddsDivisible3and7 :: Integer -> Integer -> Integer -> Integer -> [Integer]
oddsDivisible3and7 xs = [x | x <- [1..xs],x mod 3 == 0 && x mod 7 == 0,x < 200]
and the errors it is throwing:
• Couldn't match expected type ‘(Integer -> Integer -> Integer)
-> Integer -> Integer’
with actual type ‘Integer’
• The function ‘x’ is applied to two arguments,
but its type ‘Integer’ has none
In the first argument of ‘(==)’, namely ‘x mod 3’
In the first argument of ‘(&&)’, namely ‘x mod 3 == 0’
with another block for the mod 7
I'm not looking for a written function, I just need some guidance.

There are a few type error and a few sintax error, let me show:
oddsDivisible3and7 :: Integral a => a -> [a]
oddsDivisible3and7 n = [x | x <- [1..n],
x `mod` 3 == 0 && x `mod` 7 == 0 && x < 200 && x `mod` 2 /= 0]
first of all the type should be: Integral a => a -> [a]
Then, you want the divisible by 3, 7 and the odds (not divisible by 2), and all less than 200.
example:
oddsDivisible3and7 500
=> [21,63,105,147,189]

Related

Function that tells if a number ir prime or not

``
I'm a Haskell newbie and I'm defining a function that given an Int n it tells if a number is prime or not by searching for an 2<=m<=sqrt(n) that mod n m ==0
if such m exists, then n is not prime, if not then n is prime.
I'm trying to define a list with numbers m between 2 and sqrt n, that mod n m ==0
My thought is that if the list is empty then n is prime, it not, n is not prime
`
isprime' :: Int -> Bool
isprime' n | l == [] = True
| otherwise = False
where
l = [x|x<-[2.. sqrt n], mod n x == 0]
`
But there seems to be a problem with sqrt n when I run my code and I can't understand it. can someone explain what I'm doing wrong/what to change for my code to run/ and why there's an error?
Running the code gives the following error
test.hs:9:28: error:
• No instance for (Floating Int) arising from a use of ‘sqrt’
• In the expression: sqrt n
In the expression: [2 .. sqrt n]
In a stmt of a list comprehension: x <- [2 .. sqrt n]
|
9 | l = [x|x<-[2.. sqrt n], mod n x == 0]
| ^^^^^^
You are correct in saying that the error is with sqrt, but the rest is pretty opaque to a new Haskell developer. Lets try by checking the type of sqrt to see if that helps.
Prelude> :t sqrt
sqrt :: Floating a => a -> a
Here I'm using ghci to interactively write code. :t asks for the type of the preceeding expression. The line sqrt :: Floating a => a -> a says sqrt takes in some floating point number a and returns something of the same type.
Similar to our error message we see this Floating thing. this thing is a typeclass but for the sake of solving this problem we'll save understanding those for later. In essence, haskell is trying to tell you that Int is not floating point number which is what sqrt expects. We can amend that by turning our Int into a Float with fromIntegral which is a really general function for turning number types into one another. (see Get sqrt from Int in Haskell)
isprime' :: Int -> Bool
isprime' n | l == [] = True
| otherwise = False
where
asFloat :: Float -- new! - tell fromIntegral we want a float
asFloat = fromIntegral n -- new! turn n into a Float
l = [x|x<-[2..sqrt asFloat], mod n x == 0]
This also errors! but it's a new one!
test.hs:10:48: error:
• Couldn't match expected type ‘Int’ with actual type ‘Float’
• In the second argument of ‘mod’, namely ‘x’
In the first argument of ‘(==)’, namely ‘mod n x’
In the expression: mod n x == 0
|
10 | l = [x|x<-[2..sqrt asFloat], mod n x == 0]
| ^
this is saying that x is suddenly a Float. When we changed to [2..sqrt asFloat] we now have made a list of Floats ([Float]). We need to change that back to [Int]. we can do that by calling floor on the result of the square root.
isprime' :: Int -> Bool
isprime' n | l == [] = True
| otherwise = False
where
asFloat :: Float
asFloat = fromIntegral n
l = [x|x<-[2..floor (sqrt asFloat)], mod n x == 0] -- new! I added floor here to change the result of sqrt from a `Float` into a `Int`
This now correctly compiles.

Haskell Type errors

First day learning haskell, and coming from a python background I'm really having trouble debugging when it comes to type; Currently I'm working on a simple function to see if a number is a prime;
prime p = if p == 1 then False else if p == 2 then True else if maximum ([if p `mod` x == 0 then x else -1 | x<-[2..(floor(p**0.5))]]) > 0 then False else True
It works when I have a specific number instead of the generic P, but no matter what I try (and I've tried a lot, including just moving onto different problems) I always get some kind of error regarding type. For this current iteration, I'm getting the error
<interactive>:149:1: error:
* Ambiguous type variable `a0' arising from a use of `prime'
prevents the constraint `(RealFrac a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance RealFrac Double -- Defined in `GHC.Float'
instance RealFrac Float -- Defined in `GHC.Float'
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: prime 2
In an equation for `it': it = prime 2
<interactive>:149:7: error:
* Ambiguous type variable `a0' arising from the literal `2'
prevents the constraint `(Num a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Num Integer -- Defined in `GHC.Num'
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
...plus two others
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `prime', namely `2'
In the expression: prime 2
In an equation for `it': it = prime 2
If someone could, as well as debugging this particular program, give me a heads up on how to think of haskell types, I'd be incredibly grateful. I've tried looking at learnyouahaskell but so far I've had no luck applying that.
In short: by using mod, floor, and (**) all at the same time, you restrict the type of p a lot, and Haskell fails to find a numerical type to call prime.
The main problem here is in the iterable of your list comprehension:
[2..(floor(p**0.5))]
Here you call p ** 0.5, but since (**) has type (**) :: Floating a => a -> a -> a, that thus means that p has to be an instance of a type that is an instance of the Floating typeclass, for example a Float. I guess you do not want that.
Your floor :: (RealFrac a, Integral b) => a -> b even makes it worse, since now p also has to be of a type that is an instance of the RealFrac typeclass.
On the other hand, you use mod :: Integral a => a -> a -> a, so it means that your p has to be Floating, as well as Integral, which are rather two disjunctive sets: although strictly speaking, we can define such a type, it is rather weird for a number to be both Integral and Floating at the same type. Float is for instance a Floating number, but not Integral, and Int is Integral, but not a Floating type.
We have to find a way to relax the constraints put on p. Since usually non-Integral numbers are no primes at all, we better thus aim to throw out floor and (**). The optimization to iterate up to the square root of p is however a good idea, but we will need to find other means to enforce that.
One way to do this is by using a takeWhile :: (a -> Bool) -> [a] -> [a] where we take elements, until the square of the numbers is greater than p, so we can rewrite the [2..(floor(p**0.5))] to:
takeWhile (\x -> x * x <= p) [2..]
We even can work only with odd elements and 2, by writing it as:
takeWhile (\x -> x * x <= p) (2:[3, 5..])
If we test this with a p that is for instance set to 99, we get:
Prelude> takeWhile (\x -> x * x <= 99) (2:[3, 5..])
[2,3,5,7,9]
If we plug that in, we relaxed the type:
prime p = if p == 1 then False else if p == 2 then True else if maximum ([if p `mod` x == 0 then x else -1 | x <- takeWhile (\x -> x * x <= p) (2:[3, 5..])]) > 0 then False else True
we actually relaxed it enough:
Prelude> :t prime
prime :: Integral a => a -> Bool
and we get:
Prelude> prime 23
True
But the code is very ugly and rather un-Haskell. First of all, you here use maximum as a trick to check if all elements satisfy a predicate. But it makes no sense to do that this way: from the moment one of the elements is dividable, we know that the number is not prime. So we can better use the all :: (a -> Bool) -> [a] -> Bool function. Furthermore conditions are usually checked by using pattern matching and guards, so we can write it like:
prime :: Integral a => a -> Bool
prime n | n < 2 = False
| otherwise = all ((/=) 0 . mod n) divisors
where divisors = takeWhile (\x -> x * x <= n) (2:[3, 5..])
Your code can be simplified as
prime p = if p == 1 then False else
if p == 2 then True else
if maximum ([if p `mod` x == 0 then x else -1 | x<-[2..(floor(p**0.5))]]) > 0
then False else True
=
prime p = if p == 1 then False else
if p == 2 then True else
not (maximum [if p `mod` x == 0 then x else -1 | x<-[2..floor(p**0.5)]] > 0 )
=
prime p = not ( p == 1 ) &&
( p == 2 ||
maximum [if p `mod` x == 0 then x else -1 | x<-[2..floor(p**0.5)]] <= 0 )
=
prime p = p /= 1 &&
( p == 2 ||
maximum [if p `mod` x == 0 then x else -1 | x<-[2..floor(p**0.5)]] == -1 )
=~
prime p = p == 2 || p > 2 && null [x | x <- [2..floor(p**0.5)], p `mod` x == 0]
(convince yourself in the validity of each transformation).
This still gives us a type error of course, because (**) :: Floating a => a -> a -> a and mod :: Integral a => a -> a -> a are conflicting. To counter that, just throw a fromIntegral in there:
isPrime :: Integral a => a -> Bool
isPrime p = p == 2 ||
p > 2 && null [x | x <- [2..floor(fromIntegral p**0.5)], p `mod` x == 0]
and it's working:
~> filter isPrime [1..100]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

Haskell: last digit of a very large number

I'm trying to work out the last digit of a very large number. The challenge is that I'm getting the error
*** Exception: Prelude.!!: negative index
which I don't think should be possible. This happens when I try:
lastDigit [27,15,14]
Here is my code, which is based on https://brilliant.org/wiki/finding-the-last-digit-of-a-power/:
In this case, n becomes 7 and modList 7 gives the recurring sequence [1,7,9,3,1,7,9,3...], which is the first argument of (!!) in the relevant guard. The second argument of (!!) gives 1 because (y:ys) is (15,14) and rem (powers (15 ^ 14)) 4 is 1. Please help.
lastDigit :: [Integer] -> Integer
lastDigit [] = 1
lastDigit [x] = x `mod` 10
lastDigit [x,y] = x ^ y `mod` 10
lastDigit (x:y:ys)
| y == 0 && head ys /= 0 = 1
| n == 0 = 0
| n == 9 || n == 4 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 2)
| n == 2 || n == 3 || n == 7 || n == 8 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 4)
| otherwise = n
where n = mod x 10
powers xs = foldr1 (^) xs
modList n = drop 3 . take 30 $ cycle [mod x 10| x <- map (n^) $ take 4 [1..]]
You should be very specific about the types, otherwise they might get implicit converted during calculations. If you add Int type to your algorithm, ghc will not complain and run into an negative index exception
(fromIntegral $ powers (y:ys)) 2 :: Int)
but if you provide
(fromIntegral $ powers (y:ys)) 2 :: Integer)
it will result in
• Couldn't match expected type ‘Int’ with actual type ‘Integer’
• In the second argument of ‘(!!)’, namely
‘(rem (fromIntegral $ powers (y : ys)) 2 :: Integer)’
As you can see you have an implicit Int conversion there. Try to split up your function into smaller ones and provide a type signature, then you should be able to successfully align the types and calculate with Integers instead of Int.

Haskell error making a function to determine if a date entered is Valid

here's what i tried to use
validDate :: Int -> Int -> Bool
validDate d m
| d <= 31 && m elem highMonths = True
| d <= 30 && m elem lowMonths = True
| d <= 28 && m == 2 = True
| otherwise = False
where
highMonths = [1, 3, 5 , 7, 8, 10, 12]
lowMonths = [4, 6, 9, 11]
but its throwing me an error i don't quite understand.
WS1.hs:73:22:
Couldn't match expected type ‘(a0 -> [a0] -> Bool) -> [t1] -> Bool’
with actual type ‘Int’
Relevant bindings include highMonths :: [t1] (bound at WS1.hs:78:9)
The function ‘m’ is applied to two arguments,
but its type ‘Int’ has none
In the second argument of ‘(&&)’, namely ‘m elem highMonths’
In the expression: d <= 31 && m elem highMonths
I don't know where I've gone wrong, any help appreciated.
You need to use infix notation for elem:
m `elem` lowMonths
The docs for elem show that it is not an infix function (we know this because it does not have parentheses), so to use it in infix style, you have to surround it by backticks.
Contrast this with (!!), which is defined in parentheses. This means it is automatically an infix function, so it can be used between operands without backticks: xs !! 2. To make the operator prefix, you can simply wrap it in parentheses: (!!) xs 2

Haskell allow only positive input

I need to define a haskell function:
func :: Int -> Int
func 1 = 1
func 2 = 2
func x = x+1
So that it allows only positive numbers. I've already had a look at a similar question: Non-negative integers
And wrote this:
newtype Positive a = Positive a
toPositive :: (Num a, Ord a) => a -> Positive a
toPositive x
| x < 0 = error "number cannot be negative"
| otherwise = Positive x
func :: Positive a -> a
func (Positive n) = n
Which is however already throwing errors. Thoughts?
Update:
Sample error:
*Main> func 1
<interactive>:32:6:
No instance for (Num (Positive a0)) arising from the literal `1'
Possible fix: add an instance declaration for (Num (Positive a0))
In the first argument of `func', namely `1'
In the expression: func 1
In an equation for `it': it = func 1
*Main>
You forgot to call toPositive to convert an Int to a Positive. Call it this way:
func $ toPositive 1
Also, a quirk of Haskell is its handling of negative number literals. To avoid confusion with the subtraction operator, you must wrap them in parentheses:
func $ toPositive (-1)

Resources