haskell - -XStrict 在 GHC 中有什么作用吗?

标签 haskell ghc ghci

我认为-XStrict was supposed turn GHC into a Strict Haskell ,所以我尝试了无限斐波那契序列测试

my_zipWith f  x [] = []
my_zipWith f []  y = []
my_zipWith f (x:xt) (y:yt) = f x y : my_zipWith f xt yt

test_fibs n = 
    let fibs = 0 : 1 : my_zipWith (+) fibs (tail fibs) in
    take n fibs

main = do
        putStr $ show $ test_fibs 15

看看它是否会在内存中爆炸,但事实并非如此:

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.0.2

$ ghc -XStrict fibs.hs && ./fibs 
[1 of 1] Compiling Main             ( fibs.hs, fibs.o )
Linking fibs ...
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]

我做错了什么?

最佳答案

Strict pragma 当然让 GHC 严格评估所有内容,但仅限 Weak Head Normal Form 。例如:

(a, b) = (error "a", error "b")

如果上述代码存在于Strict pragma 下,则会出现任何错误。让我们看看您的代码:

test_fibs n = 
    let fibs = 0 : 1 : my_zipWith (+) fibs (tail fibs) in
    take n fibs

fibs 递归调用,但在列表 cons 中,所以现在整个列表是 WHNF。这就是您的代码无法堆栈的原因。

This post也会帮助你。享受递归和懒惰!

添加:

简单的方法,使用 deepseq :

{-# LANGUAGE Strict #-}
import Control.DeepSeq

my_zipWith f  x [] = []
my_zipWith f []  y = []
my_zipWith f (x:xt) (y:yt) = force $ f x y : my_zipWith f xt yt

test_fibs :: Int -> [Int]
test_fibs n = 
    let fibs = 0 : 1 : my_zipWith (+) fibs (tail fibs) in
    force $ take n fibs

main = do
        putStr $ show $ test_fibs 15

force 定义为 force x = x `deepSeq` xdeepSeq 将表达式按字面意思深度计算为 NF(范式)。此转换是通过 GHC.Generics 实现的。如果手动转换,只需评估数据内部,因此可以重写以下内容:

{-# LANGUAGE Strict #-}

my_zipWith f  x [] = []
my_zipWith f []  y = []
my_zipWith f (x:xt) (y:yt) = f x y : go
    where
        go = my_zipWith f xt yt

test_fibs n = 
    let
        fib2 = my_zipWith (+) fibs (tail fibs)
        fibs = 0 : 1 : fib2
    in
        take n fibs

main = do
        putStr $ show $ test_fibs 15

但它们实际上无法堆叠。因为GHC can detect infinite loop ,但这是另一个故事了。

关于haskell - -XStrict 在 GHC 中有什么作用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65433488/

相关文章:

haskell - 将当前时间转换为 Int (Haskell)

haskell - C 与 Haskell 中的朴素斐波那契

haskell - GHCi 可以告诉我本地 Haskell 函数的类型吗?

haskell - 无法将 HUnit 导入 ghci

list - 找到适当的值后,无限列表不会终止。

haskell - (!!) 整数溢出运算符

haskell - 为什么 year=year+1 不会因堆栈溢出而失败?

haskell - 需要一个类型,但 ‘Num a’ 的类型为 ‘GHC.Prim.Constraint’

haskell - 有什么方法可以在 do/while/let block 中打印出变量类型?

haskell - Monad如何符合函数的组成