Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 实现中的两个功能_Haskell_Haskell Prelude - Fatal编程技术网

Haskell 实现中的两个功能

Haskell 实现中的两个功能,haskell,haskell-prelude,Haskell,Haskell Prelude,关于haskell中^的实现,我不了解一件事: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent" | y0 == 0 = 1 | otherwise = f x0 y0 where -- f : x0 ^ y0 = x ^ y f x y | ev

关于
haskell
^
的实现,我不了解一件事:

(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0    = errorWithoutStackTrace "Negative exponent"
        | y0 == 0   = 1
        | otherwise = f x0 y0
    where -- f : x0 ^ y0 = x ^ y
          f x y | even y    = f (x * x) (y `quot` 2)
                | y == 1    = x
                | otherwise = g (x * x) (y `quot` 2) x         -- See Note [Half of y - 1]
          -- g : x0 ^ y0 = (x ^ y) * z
          g x y z | even y = g (x * x) (y `quot` 2) z
                  | y == 1 = x * z
                  | otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]

不,
fxy
不仅仅是
gxy1
gx31
调用
g(x*x)1(x*1)
,而是
fx3
调用
g(x*x)1x
。特别是,前一个参数是
x*1
,后一个参数是
x
。如果发现这样一个实例会产生语义差异或显著的性能差异,那将是令人惊讶的,但它们至少不是完全相同的东西。

您还没有复制出来。如果仔细观察,您会注意到有一条关于内联和专门化的注释——我怀疑这是相关的,尽管您认为这些定义在语义上是等价的,这是正确的。@AJFarmar我读了好几遍,仍然不明白它是如何相关的。@DanielWagner它将违反
*
的限制。具体地说,这个
@x*fromInteger 1@=@x@和@fromInteger 1*x@=@x@
。正如我所说,它将违反
@x*fromInteger 1@=@x@和@fromInteger 1*x@=@x@
@talex-Correct。1.有可能(尽管显然不推荐)编写违反类规则的实例,以及2。在最新的
base
文档中,这些法律是全新的,我知道至少有一个遗留实例违反了这些法律。我同意,但我怀疑此代码是因为这个原因而创建的。否则,
f
应该具有相同的
x*1
以保持一致性。@talex这正是我的观点:代码可能是以这种方式创建的,这样
f
就可以避免乘以1——可能是出于性能原因,在构造
1
或乘以
1
并不便宜的情况下。例如,想象一下非常大的矩阵,它是有意义的。它将节省很少的乘法运算。
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0    = errorWithoutStackTrace "Negative exponent"
        | y0 == 0   = 1
        | otherwise = g x0 y0 1
    where
          g x y z | even y = g (x * x) (y `quot` 2) z
                  | y == 1 = x * z
                  | otherwise = g (x * x) (y `quot` 2) (x * z)