2013-04-18 35 views
3

成分是在Haskell非常正常的,但我只知道,我可以定義一個複合功能的特殊行爲,說如何在`.hs`文件中爲複合函數定義'特殊'行爲?

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是okey)。

+9

你不能這樣做。 '(floor。sqrt)n'把'floor'和'sqrt'視爲變量,而不是函數,所以這應該適用於所有函數,在這個定義中恰好被稱爲'floor'和'sqrt'。也可以說'(g。f)n'。至於你的特殊專業化,這在Haskell中是不可能的,你必須得到你需要的其他方式。 – luqui

回答

13

首先,在你的GHCI例如沒有界定floorsqrt一個特殊成分。相反,它定義了一個運算符(.),它接受三個參數floor,sqrtn,並隱藏現有的標準函數(.)

然後,您將新函數應用於標準庫函數floorsqrt,這些函數將成爲新函數(.)中具有相同名稱的參數。

你得到的錯誤是因爲頂層定義不會自動隱藏現有定義,反正這顯然不是你實際想要做的。

現在,你當然可以定義一個全新的函數(希望用它自己的名字,就像在groovy的答案中一樣)來執行你的專用floor . sqrt函數,但是Haskell本身沒有辦法將它定義爲現有的專用版本功能。

您可能會想到的是,GHC中的compiler pragma rewrite rules可能會使用compiler pragma rewrite rules自動替換具有相應改進版本的特定表達式。儘管如此,您應該小心,重寫的表單與其替換的答案相同。否則,你冒着一些真正令人困惑的調試會話的風險。

1

這個怎麼樣?所有的

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) 
+0

我只是想實驗一些概念,這是我現在正在做的通常的方式。 – neizod

相關問題