12

İşlevleri.Kısmi Uygulama

Verilen bu fonksiyon:

applyTwice :: (a -> a) -> a -> a 
applyTwice f x = f (f x) 

yazar ilginç bir şekilde kullanır:

İşte
ghci> applyTwice (++ [0]) [1] 
[1,0,0] 
ghci> applyTwice ([0] ++) [1] 
[0,0,1] 

ben olmayacaktı, hangi çıkan fonksiyon geçirilen farklı parametreler olduğunu açıkça görebilirsiniz Normal olarak, bir körelmiş işlevini göz önünde bulundurmak anlamına gelir (ister misiniz?). Yani, Haskell tarafından infix kesitinde herhangi bir özel tedavi var mı? Tüm infix işlevlerine genel mi? Bir yan not olarak


, bu Haskell ve fonksiyonel programlama, ile ilk hafta ve hala kitap okuyorum.

cevap

18

Evet, bir infix operatörünü, sol ya da sağ işlenenini belirterek, diğerini boş bırakarak (tam olarak yazdığınız iki örnekte) kısmen uygulayabilirsiniz. (++ [0])\x -> x ++ [0] eşittir ederken

Yani, ([0] ++), (++) [0] veya \x -> [0] ++ x (parantez vasıtasıyla standart bir fonksiyonu içine infix operatörü açabilirsiniz hatırlıyorum) ile aynıdır.

O (``), bir infix operatörü iki argüman ile herhangi bir standart işlevini açmak için etkinleştirmek, ayrıca ters tırnakların kullanımını bilmek yararlıdır: Tüm infix operatörleri kullanılabilir

Prelude> elem 2 [1,2,3] 
True 
Prelude> 2 `elem` [1,2,3] -- this is the same as before 
True 
Prelude> let f = (`elem` [1,2,3]) -- partial application, second operand 
Prelude> f 1 
True 
Prelude> f 4 
False 
Prelude> let g = (1 `elem`) -- partial application, first operand 
Prelude> g [1,2] 
True 
Prelude> g [2,3] 
False 
+0

Yani, Haskell bilmiyorum ama '' elem 1' olarak 'aynı (1' elem \ '\) 'dir:

aşağıdaki kimlikler tutun? – Neil

+1

@Neil: Evet, öyle. –

+4

Her iki girişi de ihmal ettiğiniz bir bölüm olarak '(++) 'yi kullanmayı seviyorum. –

5

Haskell bölümleri - tekil olumsuzluk ile yabancılık nedeniyle - hariç. Bu bile, backticklerin kullanımıyla infix'e dönüştürülmeyen infix fonksiyonlarını içerir. Hatta çift taraflı bir bölüm olarak, normal fonksiyonlarına operatörleri yapmak için formülasyonun düşünebilirsiniz:

(x + y) ->(+ y) ->(+)

Bölümler olan (çoğunlukla, bazı nadir köşe vakalarla) basit lambdas olarak tedavi edilir.

\x -> (x/2)

ve (2 /) olmayan bir değişmeli operatörü ile bir örnek için, \x -> (2/x) aynıdır: (/ 2) aynıdır. Teorik olarak burada ilginç olan hiçbir şey ilginç bir şey yok. Bu infix operatörlerinin kısmi uygulanması için sözdizimsel şekerdir. Genellikle kodları biraz daha güzel yapar. (Elbette, karşı örnekleri vardır.)

+2

"Unary negation ile gariplik", "(- 1)" sayısal literal -1 olarak veya '\ x -> x - 1' fonksiyonu olarak yorumlanıp yorumlanmayacağı belirsizdir. Haskell'in yaratıcılarının tercihi, onu sayısal bir değişmez olarak yorumlamak ve x 'y-' y - x' 'leri çıkartan' eksiltme 'fonksiyonunu sağlamaktı. Aynı zamanda, tekli eksi işlevi gibi davranan "negate", yani "negate x = -x" –

+0

@ ChrisTaylor: Neredeyse sağlarlar. '(- x)', 'x' negatifini çevirir, yani '(- 1)', 'ınerden (-1) 'dan,' 'Integer (-1) 'den değil. Elbette, ikisi iyi davranışlı 'Num' örnekleri için eşdeğer olmalıdır. – hammar

+0

@hammar Ah, biraz geriye dönük mantık var. Düzeltme için teşekkürler! –

15

Evet, işte the section syntax.

Bölümler, bir ikili işleç ve e ifadesi olan (op e) veya (e op) olarak yazılmıştır. Bölümler, ikili operatörlerin kısmi uygulamaları için uygun bir sözdizimi.

(op e) = \ x -> x op e 
(e op) = \ x -> e op x