2010-03-22 50 views
6

哈斯克爾玩弄了一下後,我偶然發現了這個功能:Haskell的類型系統將數值視爲函數?

Prelude Data.Maclaurin> :t ((+) . ($) . (+)) 
((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a 

(Data.Maclaurin由包向量空間出口)。所以它需要一個民,功能,另一個民最終收益一個數字。以下工作有什麼魔力?

Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3 
6 

2顯然不是一個函數(a-> a)還是我錯過了某些東西?

+0

http://www.haskell.org/haskellwiki/Num_instance_for_functions – sdcvvc 2010-03-24 13:52:20

回答

16

Data.NumInstances模塊相同的包defines一個Num實例的用於返回的數字功能:

instance Num b => Num (a->b) where 
    (+)   = liftA2 (+) 
    (*)   = liftA2 (*) 
    fromInteger = pure . fromInteger 
    ... 

在Haskell字面像2的整數是通用的,因此,它可以表示爲Num任何實例的數目:

Prelude> :t 2 
2 :: (Num t) => t 

將它從轉換爲fromInteger在特定上下文所需要的類型,的實際數調用類。

由於上述輔助模塊定義了功能的Num一個實例,2現在可以轉換到一個功能與指定那裏fromInteger方法。 因此,ghci調用fromInteger 2以獲得作爲問題中構造的第二個參數所需的函數。整個表達式恰好評估爲6

+0

此外,* *所有應用性函子承認爲數字類這些實例。請參閱[applicative-numbers](http://hackage.haskell.org/package/applicative-numbers)軟件包,以便爲您想要的任何應用函子定義此類實例。 – Conal 2011-04-18 23:50:31

1

你有很好的理由感到困惑。使用GHC中的Data.NumInstances模塊(由Data.Maclaurin加載),可以將Num強制爲常數函數。

Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a) 
(2 :: (Num a) => a -> a) :: (Num a) => a -> a 
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0   
2 
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000 
2 

表達的評價是,本質上,

((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3 
         = ((+) (1+)) 2 3 
         -- (+) is defined for functions that return a Num 
         = ((+) (1+) (\_ -> 2)) 3 
         = ((+2) . (1+)) 3 
         = 6 
+2

不,這是不可能的,除非你有一些非標準的模塊加載,它們爲'a - > a'定義了一個'Num'實例。 – 2010-03-23 05:44:40

+1

嗯,該死的,我可以發誓這沒有Data.Maclaurin加載工作,但它沒有。正如@sth指出的那樣,這種魔法是由Data.NumInstances支持的。 – 2010-03-23 12:07:54