繁体   English   中英

Haskell:为什么会出现空列表异常?

[英]Haskell: Why this would lead to empty list exception?

我目前正在从事 Project Euler 的工作,并使用 Haskell 进行练习。 然而,我遇到了一个问题,我似乎无法产生一个更小的例子,所以这里是代码(用于项目 euler 232):

buildNum (x, y) = multNum x y 1 []
  where multNum num mul exp s = if (num > 10 ^ 100) then s else multNum nNum mul nexp ns
          where next = (num * mul) `div` exp
                ns = num:s
                top = next `mod` 10
                nexp = exp * 10
                nNum = num + nexp * top

sumBuild (x, y) = (head (buildNum (x, y))) * length (buildNum (x, y))

请忽略这里的不良风格:)

如果我加载它并在这里运行 sumBuild(7, 5) ,我会得到一个异常:

*** Exception: Prelude.head: empty list

但是,如果我将 sumBuild 更改为:

sumBuild (x, y) = head (buildNum (x, y))

要么

sumBuild (x, y) = length (buildNum (x, y))

然后它运行良好。

这对我来说真的很困惑,因为没有副作用,而且两次运行会产生不同的结果(至少看起来是这样)。 这里有什么问题?

如果有人能把这个程序编辑成一个最小的工作示例,那么我真的很感激!

谢谢你的帮助!

这是提示:

> :t sumBuild
sumBuild :: (Int, Int) -> Int
> let a = 7 :: Int
> a > 10^100
True

作为建议,请始终明确尝试 state 类型的顶级声明。 这有助于避免此类错误。

问题是,通过与length的结果相乘,这是一个Int ,您强制所有计算都使用机器大小的Int类型完成,从而导致溢出。 当您删除它时,将使用默认的任意大小的Integer类型。

如果您添加类型签名和fromIntegral以强制使用Integer完成计算,一切都会按预期进行。

buildNum :: (Integer, Integer) -> [Integer]
buildNum (x, y) = -- same as before

sumBuild :: (Integer, Integer) -> Integer
sumBuild (x, y) = (head (buildNum (x, y))) * fromIntegral (length (buildNum (x, y)))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM