Haskell: what does this method do - haskell

In my test-exam a question was, what this method does.
dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
I am new to Haskell but as far as I can say, it checks if the result of dos a = ([x | x <- [2..div a 2], mod a x == 0]) is an empty list. Also x are all numbers of a divided by 2 which have %number == 0. Thus this are all even numbers? It seems like it checks if the number is dividable through 2, if yes -> false, else otherwise. Could anyone explain to me the semantic in detail?

You are close to what is going on. There are several components to understand.
First, [2 .. div a 2] generates a list of numbers from 2 to floor(a / 2).
Next, mod a x == 0 filters out the values from 2 to floor(a / 2) which
divide a (e.g. it finds all the factors of a).
Thus, the list generated by
[x | x <- [2 .. div a 2], mod a x == 0]
contains all the numbers that divide a.
Finally, the == [] checks that
this list is empty (e.g. a has no factors). So, what this function actually
does is to determine whether or not a number is prime by attempting to
generate its factors, which is easy to see when you use dos as the predicate
for filter:
Prelude> let dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
Prelude> :t dos
dos :: Integral t => t -> Bool
Prelude> filter dos [2 .. 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] -- Prime goodness

It is the basic algorithm to check if a number is prime or not. It traverses over all the numbers from 2 to a/2 and checks if any of it divides a, if the list is empty then it means it has no factors between 2 and a/2 which implies the number is prime.

Related

Haskell Listing the first 10 numbers starting from 1 which are divisible by all the numbers from 2 to 15

--for number divisible by 15 we can get it easily
take 10 [x | x <- [1..] , x `mod` 15 == 0 ]
--but for all how do I use the all option
take 10 [x | x <- [1..] , x `mod` [2..15] == 0 ]
take 10 [x | x <- [1..] , all x `mod` [2..15] == 0 ]
I want to understand how to use all in this particular case.
I have read Haskell documentation but I am new to this language coming from Python so I am unable to figure the logic.
First you can have a function to check if a number is mod by all [2..15].
modByNumbers x ns = all (\n -> x `mod` n == 0) ns
Then you can use it like the mod function:
take 10 [x | x <- [1..] , x `modByNumbers` [2..15] ]
Alternatively, using math, we know that the smallest number divible by all numbers less than n is the product of all of the prime numbers x less than n raised to the floor of the result of logBase x n.
A basic isPrime function:
isPrime n = length [ x | x <- [2..n], n `mod` x == 0] == 1
Using that to get all of the primes less than 15:
p = [fromIntegral x :: Float | x <- [2..15], isPrime x]
-- [2.0,3.0,5.0,7.0,11.0,13.0]
Now we can get the exponents:
e = [fromIntegral (floor $ logBase x 15) :: Float | x <- p']
-- [3.0,2.0,1.0,1.0,1.0,1.0]
If we zip these together.
z = zipWith (**) p e
-- [8.0,9.0,5.0,7.0,11.0,13.0]
And then find the product of these we get the smallest number divisible by all numbers between 2 and 15.
smallest = product z
-- 360360.0
And now to get the rest we just need to multiply that by the numbers from 1 to 15.
map round $ take 10 [smallest * x | x <- [1..15]]
-- [360360,720720,1081080,1441440,1801800,2162160,2522520,2882880,3243240,3603600]
This has the advantage of running substantially faster.
Decompose the problem.
You already know how to take the first 10 elements of a list, so set that aside and forget about it. There are infinitely many numbers divisible by all of [2,15], your remaining task is to list them all.
There are infinitely many natural numbers (unconstrained), and you already know how to list them all ([1..]), so your remaining task is to transform that list into the "sub-list" who's elements are divisible by all of [2,15].
You already know how to transform a list into the "sub-list" satisfying some constraint (predicate :: X -> Bool). You're using a list comprehension in your posted code, but I think the rest of this is going to be easier if you use filter instead. Either way, your remaining task is to represent "is divisible by all of [2,15]" as a predicate..
You already know how to check if a number x is divisible by another number y. Now for something new: you want to abstract that as a predicate on x, and you want to parameterize that predicate by y. I'm sure you could get this part on your own if asked:
divisibleBy :: Int -> (Int -> Bool)
divisibleBy y x = 0 == (x `mod` y)
You already know how to represent [2,15] as [2..15]; we can turn that into a list of predicates using fmap divisibleBy. (Or map, worry about that difference tomorrow.) Your remaining task is to turn a list of predicates into a predicate.
You have a couple of options, but you already found all :: (a -> Bool) -> [a] -> Bool, so I'll suggest all ($ x). (note)
Once you've put all these pieces together into something that works, you'll probably be able to boil it back down into something that looks a little bit like what you first wrote.

Haskell - Why does this list comprehension return an infinite list?

[3 * x | x <- [1 ..], 3 * x < 20]
I don't really understand why this gives
[3,6,9,12,15,18
And doesn't find an end
The semantics of
[3 * x | x <- [1 ..], 3 * x < 20]
is to try all the elements of [1..] and keep those satisfying the filter condition 3*x<20.
A human can see that after the first x which falsifies the condition there's no point in trying all the larger values, but Haskell will try those anyway, and get stuck on a kind of infinite loop.
This is because, in the general case, the condition could become true once again, e.g.
[3 * x | x <- [1 ..], 3 * x < 20 || x == 1000000 ]
In general it is undecidable to detect whether there are no more solutions, so Haskell, like any other programming language, can not opt to stop after the last solution.
If you want the list to stop after the first value which does not satisfy the filtering condition, use takeWhile:
takeWhile (< 20) [3 * x | x <- [1 ..]]

Testing if an inputted Int is a perfect number

I've been looking into perfect numbers, and I found this interesting bit of code on rosettacode:
perfect n = n == sum [i | i <- [1..n-1], n `mod` i == 0]
Now, I understand what a perfect number is, and I know which numbers are considered perfect, however I'm struggling to work out which parts of this code do what.
I understand that it's working out the factors of the inputted number, and combining them together to see if it matches the input itself, but I'm not sure how it's doing this.
If anyone could possibly break down this bit of code in a beginner-friendly manner I'd be very appreciative.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^^^^
For i from 1 to n-1 (that is, [1, 2, 3, 4 ... n-1])
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^
And only for those values where i evenly divides n. Discarding values that do not match this requirement.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^
Include i in the result list.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
Add the elements of this list together.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
And return True iff the total equals n.
[i | i <- [1..n-1], n `mod` i == 0]
Starting from the middle, you can read it like this: for each element i of the [1..n-1] list, check if n `mod` i equals 0. If it does, include i in the result list (that's the part to the left of the |. Without using the list comprehension syntax, that might be written using the filter function:
filter (\i -> n `mod` i == 0)
The elements of the resulting list are then added with sum, and, finally, the sum is tested for equality with n.

Haskell Does Not Evaluate Lazily takeWhile

isqrt :: Integer -> Integer
isqrt = floor . sqrt . fromIntegral
primes :: [Integer]
primes = sieve [2..] where
sieve (p:ps) = p : sieve [x | x <- ps, x `mod` p > 0]
primeFactors :: Integer -> [Integer]
primeFactors n = takeWhile (< n) [x | x <- primes, n `mod` x == 0]
Here is my code. I think you guessed what I am trying to do: A list of prime factors of a given number using infinite list of prime numbers. But this code does not evaluate lazily.
When I use ghci and :l mycode.hs and enter primeFactors 24, the result is [2, 3 ( and the cursor constantly flashing there) there isn't a further Prelude> prompt. I think there is a problem there. What am I doing wrong?
Thanks.
takeWhile never terminates for composite arguments. If n is composite, it has no prime factors >= n, so takeWhile will just sit there.
Apply takeWhile to the primes list and then filter the result with n mod x, like this:
primeFactors n = [x | x <- takeWhile (<= n) primes, n `mod` x == 0]
(<= is used instead of < for maximum correctness, so that prime factors of a prime number would consist of that number).
Have an illustration of what happens:
http://sketchtoy.com/67338195
Your problem isn't directly takeWhile, but rather the list comprehension.
[x | x <- primes, n `mod` x == 0]
For n = 24, we get 24 `mod` 2 == 0 and 24 `mod` 3 == 0, so the value of this list comprehension starts with 2 : 3 : .... But consider the ... part.
The list comprehension has to keep pulling values from primes and checking 24 `mod` x == 0. Since there are no more prime factors of 24 nothing will ever pass that test and get emitted as the third value of the list comprehension. But since there's always another prime to test, it will never stop and conclude that the remaining tail of the list is empty.
Because this is lazily evaluated, if you only ever ask for the first two elements of this list then you're fine. But if your program ever needs the third one (or even just to know whether or not there is a third element), then the list comprehension will just spin forever trying to come up with one.
takeWhile (< 24) keeps pulling elements from its argument until it finds one that is not < 24. 2 and 3 both pass that test, so takeWhile (< 24) does need to know what the third element of the list comprehension is.
But it's not really a problem with takeWhile; the problem is that you've written a list comprehension to find all of the prime factors (and nothing else), and then trying to use a filter on the results of that to cut off the infinite exploration of all the higher primes that can't possibly be factors. That doesn't really make sense if you stop to think about it; by definition anything that isn't a prime factor can't be an element of that list, so you can't filter out the non-factors larger than n from that list. Instead you need to filter the input to that list comprehension so that it doesn't try to explore an infinite space, as #n.m's answer shows.

Just started with Haskell. What's wrong with my set building notation?

I'm very excited with what I've seen of Haskell, but I'm already not quite getting list comprehensions.
If I want to find the truth set of something like:
P(x): x ^ 2 < 3
Why does the expression [x | x ^ 2 < 3] return []? Am I getting the syntax wrong?
You need to provide a source list for x, e.g.
[x | x <- [0.01, 0.02 .. 3], x ^ 2 < 3]
Haskell does not just generate values from a type, you have to provide a source of data.
What you have shown in your question, [x | x ^ 2 < 3], shouldn't even compile. I suspect you have typed this into the interpreter after having defined 'x' at some point. For example:
Prelude> let x = 3
Prelude> [x | x ^ 2 < 3]
[]
In the above the list comprehension reads as 'the list of elements "x" such that the square of "X" is less than three'. Obviously this can only end up with zero or one elements. We can see the case where it produces one element in the below:
Prelude> let x = 1
Prelude> [x | x ^ 2 < 3]
[1]
Your desire to get a set of ALL elements requires you to define an input (I'm ignoring the fact that this is a LIST and not a set - but it is important so if you didn't realize that then look into it). For example, the naturals:
Prelude> take 10 [x | x <- [0..], x ^ 2 < 3]
[0,1^CInterrupted.
This computation is a little closer. For each value in 0, 1, 2... test if its square is less than three and (if so) return it as the next element of the list. Unfortunately, list comprehension preserves no knowledge about the structure of the domain - numbers from 2 upward will be tested (until the end of our input list, which in this case is the max bound of Int) giving it the appearance of non-termination.
Instead, we can define a domain and, knowing the behavior of our predicate, only accept elements while it holds:
Prelude> takeWhile (\x -> x^2 < 3) [0..]
[0,1]

Resources