Learning Haskell, care to help out with coding style? - haskell

I started learning haskell yesterday and I got stuck on a problem. After a bit of trying different things I thought I'd finally come here and ask how to fix this. Also, feel free to criticize the way I have done things so far so I can know what direction to go. Thanks.
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
primes :: [Int]
primes = [x| x <- [1..],length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
lessen :: Int -> Int
lessen a = ceiling(sqrt(a))

To fix your type error, you want this:
lessen :: Int -> Int
lessen a = ceiling (sqrt (fromIntegral a))
a has type Int, but sqrt is expecting a floating point type, and the easiest way to convert an integral type to another numeric type is fromIntegral.

In addition to the type error in lessen you have a logic error in primes:
length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2
You're (rightly) only considering elements up to lessen x. This has the consequence that the list will almost never have exactly x - 2 elements. As a consequence you'll get into an infinite loop when trying to get more than two elements out of that list (because there is no 3rd element for which the condition is true, but haskell doesn't know that so it iterates to infinity trying to find it).
Also note that taking the length of a list is an O(n) operation and there's almost always a better way to achieve what you want.
As a style note, I would recommend defining a separate method isPrime. This will make your code look like this:
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
isPrime x = length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
primes :: [Int]
primes = [x| x <- [1..], isPrime x]
lessen :: Int -> Int
lessen a = ceiling(sqrt (fromIntegral a))
This IMHO makes the list comprehension much more readable. However it still contains the bug. To get rid of the bug, I'd suggest defining isPrime using a different approach. Going up to lessen x is fine (except you should start from 2 because 1 cleanly divides everything), but instead of building a new list with all the divisors, you should just check whether any of the numbers in the range divides x. For this we can use the higher order function any, so we get this:
isPrime x = not (any (\a -> mod x a == 0) [2 .. lessen x])

Related

Solving a problem recursively regarding access to certain elements of an infinite list

My problem itself is not important at all, but I will state it so you can understand what essentially I'm trying to understand.
Nicomano said that you can calculate the cube of a natural number m like this:
for m=1, take the first odd number, sum them, and that is the cube (1^3 = 1)
for m=2, take the two next odds numbers,sum them, and that is the cube (2^3 = 3 + 5)
for m=3, take the three next odds numbers, sum them, and that is the cube (3^3 = 7 + 9 + 11)
And so on.
Solving this is easy just like this
--first we create an infinite odd list
odds :: [Integer]
odds = [i | i<-[1..], not (even i)]
--now the function
nicomano :: Int -> Integer
nicomano m = sum (take m (drop (sum[1..(m-1)]) odds))
Problem is, if I want to solve this recursively. When I try to do this, I ask myself the relation (mathematically speaking) between one nicomano m iteration and the previous one nicomano m-1.
The relation I found is the following one:
nicomano m = take (sum [1..m]) odds - (nicomano(1)+nicomano(2)+...+nicomano(m-1))
But this won't work to find a recursive solution, as I need the previous values of nicomano function for calculating the nicomano(m) one, and Haskell doesn't allow saving values in a list like in Python for example. Also If I could do it, it wouldn't be a recursive solution.
So how could we do this? Isn't it a good approach for finding recursive solutions to ask yourself about the relationship between one step and another?
Your current function Int -> Integer is just f m = m ** 3, and there's no nice recurrence to exploit in the nicomano manner.
Instead, I would suggest you build a function to generate the list of odds for the respective step:
nicomano :: Int -> [Integer]
nicomano 0 = [1, 3..]
nicomano n = drop n $ nicomano $ n - 1
cube :: Int -> Integer
cube n = sum $ take n $ nicomano $ n - 1
You might also find a tail-recursive formulation of this, but I think that's more ugly.
Another approach, specially suited for lazy evaluation of Haskell, is building an infinite sequence:
cube :: Int -> Integer
cube = \n -> cubes !! n
where
cubes = nicomano 0 [1, 3..]
nicomano i odds = let (begin, rest) = splitAt i odds
in sum begin : nicomano (i+1) rest

Euler 26 in Haskell

I'm trying to solve problem #26 from Project Euler in Haskell, but I have encountered some problems.
I've managed to figure out that the recurring cycle of the reciprocal is only related to its prime divisors, so I think I just need to find out a reciprocal of a prime number with the longest recurring cycle. So I wrote a algorithm in Haskell:
isPrime :: Int -> Bool
isPrime k
| k <= 1 = error "Seriously?"
| otherwise = null [ x | x <- [2..floor(sqrt(fromIntegral k))], k `mod` x == 0]
lp = [x | x <- [7..1000], isPrime x]
s = map (\n -> head [x | x <- [ceiling(logBase 10 (fromIntegral n))..], 10^x `mod` n == 1]) lp
main::IO()
main = print $ maximum s
However, it cannot produce an answer. I have tried using the lamda, which could produce the digits of recurring cycle, with a few prime numbers and I manage to get the right count of digits (I hope there would be no problem with the algorithm). I have also checked the output of the list s, which produced [6,2,6,16,18,45,23,15,3,5,63, without an end. I have no idea why it is the case, since if I manually apply the function to each prime number I can get the right output.
Can anybody tell me what is wrong with my code, or is my way of solving it turns out to be wrong? Thanks.
Int is not a good choice here, since you operate pretty big numbers, with the 10^x. Int is Bounded, so wraps around past its upper bound:
> maxBound :: Int
9223372036854775807
> (maxBound :: Int) + 1
-9223372036854775808
Omitting the signature for isPrime altogether, we get
> :t lp
lp :: Integral b => [b]
Trying
> map (\n -> (n, head [x | x <- [ceiling(logBase 10 (fromIntegral n))..],
10^x `mod` n == 1]))
(lp :: [Int])
[(7,6),(11,2),(13,6),(17,16),(19,18),(23,45),(29,23),(31,15),(37,3),(41,5),(43,63),
(47,Interrupted.
we see that your calculation gets stuck on 47. But using [Integer] (or nothing at all, so it defaults to Integer by itself), we successfully get the full result. You just misinterpret it. Re-read the problem statement, and you'll see.
(also, the answer for 43 in the above snippet is incorrect, while those for 7, 11, 13 are correct. Getting wrong results for bigger numbers is a strong signal that we have some integer wrap-around arithmetic errors going on; and that's how I found it out).

How can I replace generators if I need only one result?

I'm playing with Haskell for first time.
I've created function that returns first precise enough result. It works as expected, but I'm using generator for this. How can I replace generator in this task?
integrateWithPrecision precision =
(take 1 $ preciseIntegrals precision) !! 0
preciseIntegrals :: Double -> [Double]
preciseIntegrals precision =
[
integrate (2 ^ power) pi | power <- [0..],
enoughPowerForPrecision power precision
]
You can use the beautiful until function. Here it is:
-- | #'until' p f# yields the result of applying #f# until #p# holds.
until :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x = x
| otherwise = until p f (f x)
So, you can write your function like this:
integrateWithPrecision precision = integrate (2 ^ pow) pi
where
pow = until done succ 0
done pow = enoughPowerForPrecision pow precision
In your case, you do all the iteration and then compute a result just once. But until is useful even when you need to compute a result at each step - just use an (iter, result) tuple and then just extract the result at the end with snd.
It seems like you want to check higher and higher powers until you get one that satisfies a requirement. This is what you could do: First you define a function to get enough power, and then you integrate using that.
find gets the first element of a list that satisfies a condition – like being enough of a power! Then we need a fromJust to get the actual value from that. Please note that almost always, fromJust is a terrible idea to have in your code. However, in this case the list is infinite, so we will have troubles with infinite loops long before fromJust is able to crash the program.
enoughPower :: Double -> Int
enoughPower precision =
fromJust $ find (flip enoughPowerForPrecision precision) [0..]
preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi
The function
\xs -> take 1 xs !! 0
is called head
head [] = error "Cannot take head of empty list"
head (x:xs) = x
Its use is somewhat unsafe, as shown it can throw an error if you pass it an empty list, but in this case since you can be certain your list is non-empty it's fine.
Also, we tend not to call these "generators" in Haskell as they're not a special form but are instead a simple consequence of lazy evaluation. In this case, preciseIntegrals is called a "list comprehension" and [0..] is nothing more than a lazily generated list.

Convert Int into [Int]

I'm looking through a past exam paper and don't understand how to convert Int to [Int].
For example, one of the questions asks us to produce a list of all the factors of a whole number excluding both the number itself and 1.
strictFactors Int -> [Int]
strictFactors x = ???
I'm not asking for anyone to do this question for me! I just want to know how I'd convert an integer input to a list of integer output. Thanks!
Perhaps it would be easiest to have a look at some similar code. As requested, I won't give you the answer, but you should be able to use these ideas to do what you want.
Brute force
Here we're just going to use all the pairs of numbers between 1 and x to test if we can make x as the sum of two square numbers:
sumOfSquares :: Int -> [Int]
sumOfSquares x = [ (a,b) | a <- [1..x], b <- [a..x], a^2 + b^2 == x]
You call this like this:
ghci> asSumOfSquares 50
[(1,7),(5,5)]
because 50 = 1^2+7^2 and also 50 = 5^2 + 5^2.
You can think of sumOfSquares as working by first taking an a from the list [1..x] of numbers between 1 and x and then another between that and x. It then checks a^2 + b^2 == x. If that's True, it adds (a,b) to the resulting list.
Generate and check
This time let's generate some single numbers then check whether they're a multiple of another. This will calculate the least common multiple (lcm). For example, the least common multiple of 15 and 12 is 60, because it's the first number that's in both the 15 and 12 times tables.
This function isn't of the type you want but it uses all the techniques you want.
lcm :: Int -> Int -> Int
lcm x y = head [x*a | a <- [1..], (x*a) `mod` y == 0]
You can call that like this:
ghci> lcm 12 15
60
This time the list of numbers [1..] is (in principle) infinite; good job we're just picking the first one with head!
(x*a) `mod` y == 0 does the checking to see whether the number x*a is a multiple of y (mod gives the remainder after division). That's a key idea you should use.
Summary
Use a <- [1..end] to generate numbers, test them with a True/False expression (i.e. a Bool), perhaps using the mod function.
I'm quite new at Haskell but can think of a myriad ways of "converting" an Int to a list containing that same Int:
import Control.Applicative (pure)
sane_lst :: Int -> [Int]
sane_lst x = [x]
lst :: Int -> [Int]
lst x = take 1 $ repeat x
lst' :: Int -> [Int]
lst' = replicate 1
lst'' :: Int -> [Int]
lst'' = return
lst''' :: Int -> [Int]
lst''' = pure
lst'''' :: Int -> [Int]
lst'''' x = enumFromTo x x
I guess the point here is that you don't "convert" to a list, you rather "construct" the list you need. The staightforward strategy for the kind of question you posed is to find something that will give you a suitable starting list to work with based on your parameter, then filter, fold or comprehend as needed.
For example when I say:
lst x = take 1 $ repeat x
I'm first constructing an infinite list repeating the value I passed in, and then taking from it a list containing just the first element. So if you think about what kind of list you need to start with to find the solution to your problem you'll be halfway there.
If your only goal is to convert between the types (for now) then strictFactors x = [x] is the most canonical answer. This function is also called pure since [] is what's known as an Applicative and return since [] is known as a Monad.

Project euler problem 3 in haskell

I'm new in Haskell and try to solve 3 problem from http://projecteuler.net/.
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My solution:
import Data.List
getD :: Int -> Int
getD x =
-- find deviders
let deriveList = filter (\y -> (x `mod` y) == 0) [1 .. x]
filteredList = filter isSimpleNumber deriveList
in maximum filteredList
-- Check is nmber simple
isSimpleNumber :: Int -> Bool
isSimpleNumber x = let deriveList = map (\y -> (x `mod` y)) [1 .. x]
filterLength = length ( filter (\z -> z == 0) deriveList)
in
case filterLength of
2 -> True
_ -> False
I try to run for example:
getD 13195
> 29
But when i try:
getD 600851475143
I get error Exception: Prelude.maximum: empty list Why?
Thank you #Barry Brown, I think i must use:
getD :: Integer -> Integer
But i get error:
Couldn't match expected type `Int' with actual type `Integer'
Expected type: [Int]
Actual type: [Integer]
In the second argument of `filter', namely `deriveList'
In the expression: filter isSimpleNumber deriveList
Thank you.
Your type signature limits the integer values to about 2^29. Try changing Int to Integer.
Edit:
I see that you already realised that you need to use Integer instead of Int. You need to change the types of both getD and isSimpleNumber otherwise you will get a type mismatch.
Also in general, if you are having trouble with types, simply remove the type declarations and let Haskell tell you the correct types.
Main> :t getD
getD :: Integral a => a -> a
Main> :t isSimpleNumber
isSimpleNumber :: Integral a => a -> Bool
After you found the error, may I point out that your solution is quite verbose? In this case a very simple implementation using brute force is good enough:
getD n = getD' n 2 where
getD' n f | n == f = f
| n `mod` f == 0 = getD' (n `div` f) f
| otherwise = getD' n (succ f)
this question is easy enough for brute-force solution, but it is a bad idea to do so because the whole idea of project euler is problems you need to really think of to solve (see end of answer)
so here are some of your program's flaws:
first, use rem instead of mod. it is more efficient.
some mathematical thinking should have told you that you don't need to check all numbers from 1 to x in the isprime function and the getD function, but checking all numbers from the squareroot to one (or reversed) should be sufficient. note that in getD you will actually need to filter numbers between x and the square root, because you search for the biggest one.
why do you use the maximum function in getD? you know the list is monotonically growing, so you may as well get the last one.
despite you only need the biggest divisor (which is prime) you compute the divisors list from small to big making the computer check for each value if it is a divisor or not although discarding the result once a bigger divisor is found. it should be fixed by filtering the list of numbers from x to 1, not from 1 to x. this will cause the computer to check divisibility (how should I say that?) for the biggest possible divisor, not throwing to the trash the knowledge of previous checks. note that this optimization takes effect only if the previous point is optimized, because otherwise the computer will compute all divisors anyway.
with the previous points mixed, you should have filtered all numbers [x,x-1 .. squareroot x] and taken the first.
you don't use an efficient isPrime function. if I were you, I would have searched for an isprime library function, which is guaranteed to be efficient.
and there are more..
with this kind of code you will never be able to solve harder project euler problems. they are designed to need extra thinking about the problem (for instance noticing you don't have to check numbers greater from the square root) and writing fast and efficient code. this is the purpose of project euler; being smart about programming. so don't skip it.

Resources