代码之家  ›  专栏  ›  技术社区  ›  nedned

Haskell编译器如何处理where语句?

  •  3
  • nedned  · 技术社区  · 16 年前

    在下面的函数中,我想知道编译器是否足够聪明来解决这个问题 x 是保持不变,还是计算列表中每个项目的列表头?(我用的是GHC)

    allSame :: Eq a => [a] -> Bool 
    allSame xs = all (==x) xs  where x = head xs
    
    2 回复  |  直到 16 年前
        1
  •  11
  •   Don Stewart    16 年前

    GHC中where的语义是为x分配一个闭包,并在所有使用中共享。将为函数(='x')生成一个新的闭包,优化器将把它浮出来,这样每次遍历只生成一次。

    要查看生成的代码,请检查核心(例如通过ghc核心)。GHC优化代码以:

    M.allSame a eq xs =
        all
          (let 
             ds =
               case xs of 
                 []   -> error "bad head"
                 x : _-> x
                in
              \y -> x == y
             ) xs
    

        2
  •  0
  •   Community Mohan Dere    6 年前

    我认为Haskell只会评估需要什么:所以它在寻找 x 发现它在 where 一次又一次 all .

    myall 它做了一个类似于 all (==x) ,但实际上只是打印出比较元素。所以你会看到,如果你每次都有一个新的论点,或者每次都是一样的。

    编辑:

    下面是一个小函数来测试: myall公司 只需收集第一个参数并将其放入列表中。

    myall x [] = [x]
    myall x xs =  x:(myall x (tail xs))
    
    test xs = myall (x) xs where x = head xs
    

    test [1,2,3] ,您将看到结果是 [1,1,1,1] ,即首先 被评估为 1 myall公司 进行评估。