如何在`.hs`文件中定义复合函数的'特殊'行为?

nei*_*zod 3 haskell

在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
Run Code Online (Sandbox Code Playgroud)

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

现在我想做同样的内部.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)
Run Code Online (Sandbox Code Playgroud)

这次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')
Run Code Online (Sandbox Code Playgroud)

那么可以在.hs文件中定义这样的函数吗?(但是在里面mainletokey 定义它).

C. *_*ann 13

首先,在你的GHCI例如没有界定的特殊成分floorsqrt.相反,它定义了运营商(.)这需要命名的三个参数floor,sqrt以及n和隐藏命名现有的标准功能(.).

然后,应用新功能,标准库函数floorsqrt,成为在新的相同名称的参数(.)功能.

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

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

您可能正在考虑并且可能在GHC中使用编译器编译指示重写规则来自动使用等效的改进版本替换特定表达式.但是,您应该小心,您的重写形式会给出与其替换相同的答案.否则你会冒一些令人困惑的调试会话.