1
votes

I've written a Haskell program for problem 25 on Euler. I think my program should run and return the correct answer, but it doesn't:

-- Problem25.hs
module Main where

fib :: Int -> Integer
fib 1 = 1
fib 2 = 1
fib n = fib (n-1) + fib (n-2)

length1 :: Integer -> Int
length1 = length . show

main :: IO ()
main = do
  list1 <- [1..]
  list2 <- zip3 list1 list1 list1
  list3 <- map funct list2
    where funct u v w = (u, fib u, length1 (fib u))
  putStrLn "number : "                                                 -- line 17
  putStrLn $ show . head . ( dropWhile ( \(u,v,w)-> w < 1000  ) list3)  

However, I get the following error:

$ ghc Problem25.hs
[1 of 1] Compiling Main             ( Problem25.hs, Problem25.o )

Problem25.hs:17:3: parse error on input `putStrLn'

Why do I get the parser error? I'm in a do block, so putStrLn "number : " should be fine, right?

1
Always post the exact error message.Zeta
@zeta the first only led to quite a few more ... this would be never-ending but huntRandom Dev

1 Answers

2
votes

ok here is a version with all syntax errors removed:

module Main where

fib :: Int -> Integer
fib 1 = 1
fib 2 = 1
fib n = fib (n-1) + fib (n-2)

length1 :: Integer -> Int
length1 = length . show

main :: IO()
main = do
  putStrLn "hello"

  let liste = [1..]
  let liste2 = zip3 liste liste liste
  let liste3 = map funct liste2
  putStrLn "number : "
  putStrLn $ show . head $ (dropWhile ( \(_,_,w)-> w < 1000  ) liste3)  
    where funct (u,_,_) = (u,fib u,length1 (fib u))

as you can see there are quite a few:

  • where in the middle of a do block -> this has to go to the end
  • <- instead of let ... = ... - remember: <- is to pull out values form computations - in this case to get an a from an IO a
  • one . to many in the last putStrLn (the last part with dropWhile is a value not a function)
  • a few places where you have to use a 3-tuple argument instead of the curried version as you choose to go with zip3 (that returns tuples)

also note that while this compiles and runs it will most likely not be a good (or even feasible) solution - I did nothing more than remove your syntax problems - to get a good solution you should first work on your fib (which does not perform very well - there are better ways to compute it - hint: search for Haskell + Fib on your fav. search engine)

here are a few remarks:

  • you don't need the zip3 part with 3 times the same list - you can let your funct do this work (which btw: you already do - you ignore the second and third argument)
  • why do you dropWhile and then take the head? (filter and head seems more natural IMO)
  • of course you should also rethink the funct part (notice how you never need the middle item from the tuples?)

Good luck with the rest of the exercise ;)


a bit cleaned up

I cleaned up your solution a bit:

fib :: Int -> Integer
fib 1 = 1
fib 2 = 1
fib n = fib (n-1) + fib (n-2)

length1 :: Integer -> Int
length1 = length . show

solve :: Int
solve = head . filter ((>= 1000) . length1 . fib) $ [1..]

main :: IO()
main = do
  putStrLn "number : "
  print solve

that's still not better performance wise (that's your challange) but at least it works for 3 digits instead of 1000 (although even 10 will take quite some time with this ...)

enjoy


cannot help it

I had to try it and indeed if you define the sequence like this:

import Data.List (unfoldr)

fibs :: [Integer]
fibs = unfoldr fib (1,1)
  where fib (n,m) = Just (n,(m,n+m))

(which is near to what you would usually do in a loop)

you get the answer rather quickly (4782)

of course you have to think about how to get the index to this (hint: now a zip might be a good idea)