相关疑难解决方法(0)

Haskell类型令人沮丧,简单的"平均"功能

我正在和初学者Haskell一起玩,我想写一个普通的函数.这似乎是世界上最简单的事情,对吧?

错误.

似乎Haskell的类型系统禁止平均处理泛型数字类型 - 我可以使它在Integrals列表或Fractionals列表上工作,但不能同时工作.

我想要:

average :: (Num a, Fractional b) => [a] -> b
average xs = ...
Run Code Online (Sandbox Code Playgroud)

但我只能得到:

averageInt :: (Integral a, Fractional b) => [a] -> b
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)
Run Code Online (Sandbox Code Playgroud)

要么

averageFrac :: (Fractional a) => [a] -> a
averageFrac xs = sum xs / fromIntegral (length xs)
Run Code Online (Sandbox Code Playgroud)

而第二个似乎工作.直到我尝试传递变量.

*Main> averageFrac [1,2,3]
2.0
*Main> let x = [1,2,3]
*Main> :t x
x :: [Integer]
*Main> averageFrac x

<interactive>:1:0:
    No …
Run Code Online (Sandbox Code Playgroud)

haskell types typeclass

68
推荐指数
3
解决办法
3万
查看次数

Haskell中的懒惰和尾部递归,为什么会崩溃?

我有这个相当简单的函数来计算大列表元素的平均值,使用两个累加器来保存到目前为止的总和以及到目前为止的计数:

mean = go 0 0
    where
      go s l []     = s / fromIntegral l
      go s l (x:xs) = go (s+x) (l+1) xs

main = do
  putStrLn (show (mean [0..10000000]))
Run Code Online (Sandbox Code Playgroud)

现在,用严格的语言,这将是尾递归,并且没有问题.然而,由于Haskell很懒,我的谷歌搜索让我明白(s + x)和(l + 1)将作为thunk传递递归.所以整件事崩溃和烧伤:

Stack space overflow: current size 8388608 bytes.
Run Code Online (Sandbox Code Playgroud)

进一步的谷歌搜索后,我发现seq$!.这似乎我不理解,因为我在这种情况下使用它们的所有尝试都证明是徒劳的,错误信息说的是关于无限类型的东西.

最后我发现-XBangPatterns,它通过改变递归调用来解决所有问题:

go !s !l (x:xs) = go (s+x) (l+1) xs
Run Code Online (Sandbox Code Playgroud)

但我对此并不满意,因为-XBangPatterns目前这是一个扩展.我想知道如何在不使用的情况下严格评估-XBangPatterns.(也许还可以学到一些东西!)

只是让你理解我缺乏理解,这就是我尝试过的(编译的唯一尝试,即):

go s l (x:xs) = go (seq s (s+x)) (seq l (l+1)) xs …
Run Code Online (Sandbox Code Playgroud)

optimization performance haskell lazy-evaluation ghc

18
推荐指数
3
解决办法
3057
查看次数