2010-03-22 18 views
6

Haskell etrafında biraz oynadıktan sonra bu işlevin üzerinde tökezledi:Haskell'in tip sistemi, sayısal bir değeri fonksiyon olarak değerlendiriyor mu?

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

(Data.Maclaurin paket vektör boşlukla ihraç edilmektedir.) Bu yüzden bir Num, bir işlev, bir başka Num ve sonuçta döner alır bir Num. Hangi sihir aşağıdaki işi yapıyor?

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

2 açıkçası bir işlev değil (a-> a) veya bir şeyleri kaçırdım mı?

+0

http://www.haskell.org/haskellwiki/Num_instance_for_functions – sdcvvc

cevap

16

numaralarını döndürmez fonksiyonlar için aynı paketin defines bir Num örneğinin Data.NumInstances modülü:

o Num herhangi örneği için bir sayısını temsil böylece 2 gibi edebi bir tamsayı genel olduğu Haskell'de
instance Num b => Num (a->b) where 
    (+)   = liftA2 (+) 
    (*)   = liftA2 (*) 
    fromInteger = pure . fromInteger 
    ... 

:

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

belirli bir bağlamda gerekli olan türü, fromInteger gerçek bir numaraya çevirmek içinsınıfı denir.

yukarıda belirtilen yardımcı modül fonksiyonları için Num bir örneğini tanımladığından

, 2 şimdi belirtilen fromInteger yöntemi ile bir fonksiyonu dönüştürülebilir. Yani GHCi söz konusu yapının ikinci parametre olarak gerekli işlevi almak için fromInteger 2 çağırır. Tüm ifade daha sonra 6'a değerlendirmek için olur.

+0

Ayrıca, * tüm * uygulamalı fanktorlar sayısal sınıfları için bu örnekleri kabul . İstediğiniz uygulamalı türlü funktor için böyle örneklerini tanımlamak için kolay bir yol için [uygulamalı-numaralar] (http://hackage.haskell.org/package/applicative-numbers) paketini bakın. – Conal

1

Sen iyi bir neden karıştırılmamalıdır gerekiyor. (Data.Maclaurin yüklendiğinde) ghc içinde Data.NumInstances modülü kullanarak sabit bir işleve bir Num zorlamak için mümkündür.

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 

ifadesinin değerlendirilmesi, esas olarak, bir

((+) . ($) . (+)) 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

Hayır, a -> a 'için bir' Num 'örneğini tanımlayan standart dışı modülleriniz olmadıkça mümkün değil. –

+1

Eh, lanet olsun, bu Data.Maclaurin yüklü olmadan çalıştı yemin ederim, ama değil. @sth'nin işaret ettiği gibi, bu sihir Data.NumInstances tarafından etkinleştirilir. –