3

组合在 Haskell 中很正常,但我只知道我可以定义组合函数的特殊行为,说

Prelude> (floor . sqrt) (10^55)
3162277660168379365112938496
Prelude> let (floor . sqrt) n | n < 2 = n | otherwise = head $ dropWhile (\x -> x^2 > n) $ iterate (\x -> (x + n `div` x) `div` 2) (n `div` 2)
Prelude> (floor . sqrt) (10^55)
3162277660168379331998893544

特殊定义函数的结果是正确的(因为第一个浮点错误)。

现在我想做同样的内部.hs文件,比如

(floor . sqrt) n
    | n < 2 = n
    | otherwise = head $ dropWhile (\x -> x^2 > n)
                       $ iterate (\x -> (x + n `div` x) `div` 2) (n `div` 2)

main = do
    print $ (floor . sqrt) (10^55)

这次ghc骂我

Ambiguous occurrence `.'
It could refer to either `Main..', defined at me.hs:1:8
                      or `Prelude..',
                         imported from `Prelude' at me.hs:1:1
                         (and originally defined in `GHC.Base')

那么是否可以在.hs文件中定义这样的函数?main(但是,在里面定义它let是好的)。

4

2 回答 2

13

首先,您在 GHCi 中的示例没有定义floorand的特殊组合sqrt。相反,它定义了一个运算符,该运算符(.)接受三个名为floorsqrt和的参数,n并隐藏现有的名为 的标准函数(.)

然后,您将新函数应用于标准库函数floorsqrt,它们将成为新(.)函数中具有相同名称的参数。

您得到的错误是因为顶级定义不会自动隐藏现有定义,无论如何这显然不是您真正想要做的。

现在,您当然可以定义一个全新的函数(希望有自己的名称,如 groovy 的回答)来执行您的专用floor . sqrt功能,但 Haskell 本身无法将其定义为现有功能的专用版本。

您可能正在考虑并且可能的是,在 GHC 中使用编译器编译指示重写规则来自动将特定表达式替换为等效的改进版本。不过,您应该小心,您重写的表格给出的答案与其替换的答案相同。否则,您将面临一些非常令人费解的调试会话的风险。

于 2013-04-18T18:10:41.693 回答
1

How about this?

floorSqrt n
    | n < 2     = n
    | otherwise = head $ dropWhile (\x -> x^2 > n)
                       $ iterate (\x -> (x + n `div` x) `div` 2) (n `div` 2)

main = do
    print $ floorSqrt (10^55)
于 2013-04-18T18:07:57.793 回答