【问题标题】:Why do I get a parser error in my program?为什么我的程序中出现解析器错误?
【发布时间】:2015-11-12 20:42:24
【问题描述】:

我为problem 25 on Euler 编写了一个Haskell 程序。我认为我的程序应该运行并返回正确的答案,但它没有:

-- 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)  

但是,我收到以下错误:

$ ghc Problem25.hs [1 of 1] 编译 Main (Problem25.hs, Problem25.o) 问题 25.hs:17:3:输入“putStrLn”时解析错误

为什么会出现解析器错误?我在do 区块中,所以putStrLn "number : " 应该没问题,对吧?

【问题讨论】:

  • 总是发布 exact 错误信息。
  • @zeta 第一个只会导致更多……这将是永无止境的,但狩猎

标签: haskell


【解决方案1】:

好的,这是一个删除了所有语法错误的版本:

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))

如您所见,有很多:

  • wheredo 块的中间 -> 这必须到最后
  • &lt;- 而不是 let ... = ... - 请记住:&lt;-从计算中提取值 - 在这种情况下,从 IO a 获取 a
  • 一个.到最后一个putStrLn(最后一个dropWhile是一个值而不是一个函数)
  • 在您选择使用 zip3(返回元组)时,您必须使用 3 元组参数而不是 curried 版本的一些地方

还请注意,虽然它可以编译并运行,但它很可能不是一个好的(甚至是可行的)解决方案 - 我所做的只是消除了您的语法问题 - 要获得一个好的解决方案,您应该首先处理您的 fib (它的性能不是很好 - 有更好的计算方法 - 提示:在你最喜欢的搜索引擎上搜索 Haskell + Fib)

这里有几点说明:

  • 您不需要 zip3 部分与 3 次相同的列表 - 您可以让您的 funct 完成这项工作(顺便说一句:您已经这样做了 - 您忽略了第二个和第三个参数)
  • 你为什么dropWhile然后拿人头? (filter 和 head 看起来更自然 IMO)
  • 当然,您还应该重新考虑funct 部分(注意您如何从不需要元组的中间项?)

祝你在接下来的练习中好运;)


稍微整理一下

我稍微清理了你的解决方案:

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

这仍然不是更好的性能(这是你的挑战),但至少它适用于 3 数字而不是 1000(尽管即使 10 也需要相当长的时间......)

享受


忍不住

我必须尝试一下,如果你这样定义序列:

import Data.List (unfoldr)

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

(这与您通常在循环中执行的操作很接近)

您很快就会得到答案 (4782)

当然,您必须考虑如何将 index 设为此(提示:现在zip 可能是个好主意)

【讨论】:

  • unfoldr?为什么不fibs = 1 : 1 : zipWith (+) fibs (tail fibs)? (这是我经常使用和看到的变体)
  • 因为我喜欢他们unfolds ;) (但这肯定会得到类似的结果) - 为什么不将其添加为答案?
  • 即使 10000 也相当快,并且列表只需要大约 300MB 左右:D
  • 嗯? 300MB? unfoldr 是否不受列表融合的影响? ghc -e "let fibs = 1 : 1 : zipWith (+) fibs (tail fibs) in Data.List.findIndex (&gt;10^10000) fibs" +RTS -s 产生 21MB 的总内存使用量。
  • 在 Emacs 中使用 GHCi :D(为什么要编译它)
猜你喜欢
  • 2020-02-15
  • 2014-11-30
  • 2022-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多