2014-11-16 20 views
7

Sadece Haskell'i öğrenmeye başladım ve benim için garip olan şeylerden biri, birden fazla argümanı olan bir fonksiyonun türünün sözdizimi. Haskell neden bir işlev türü için okları kullanıyor?

basit bir örnek ele alalım:

(+) :: Num a => a -> a -> a 

burada hepimiz okları ihtiyaç Neden? Num Num Num -> Num gibi bir şey yazmak daha mantıklı olmaz mıydı?

Kaputun altındaki sebep nedir? Bu soruyu araştırdım ama gerçekten yararlı bir şey bulamadım.

+0

Eğer (Ord a, Num a) => a -> a -> a 'olsaydınız ne yazardınız? Bağlantı için – Squidly

cevap

16

Kafa karıştırıcı şeyler olan ilk şey, Num a =>, yani şimdilik bunu tamamen yok sayacağız. Bunun yerine, verdiğiniz tip imzasının olası bir uzmanlığı olan Int -> Int -> Int'u düşünelim.

Haskell'de işlevler neredeyse her zaman curried'dur. Bu, çoklu argüman fonksiyonunun aslında bir sonraki argümanı alan bir işlevi döndüren bir argümanın işlevi olduğu anlamına gelir.

-> doğru ilişkilendiricidir, bu nedenle Int -> Int -> IntInt -> (Int -> Int) ile aynı şeydir.

Bu aynı zamanda bu tanım

f :: Int -> Int -> Int 
f x y = x + y 

f :: Int -> Int -> Int 
f x = \y -> x + y 

Aslında aynı olduğu anlamına gelir, Haskell tüm fonksiyonları tam olarak bir argüman alır. Tuples de var, ama onlar birinci sınıf vatandaşlar, bu yüzden onlar sadece bir argüman listesi daha vardır.

Num a =>, tür sisteminin farklı bir yönüdür. a tür değişkeninin Num tip sınıfının bir örneği olması gerektiğini söylüyor. Num örnekleri olan yaygın örnek örnekleri Int ve Double içerir. Yani Num bir tür değil, bir tür sınıfıdır. Num a =>, a tür değişkeni üzerinde bir kısıtlamayı temsil eder, bu işlev için başka bir argüman değildir. Eğer (+) kullanmak için bu şekilde a sınırlamak gerekir böylece

(+) yöntem Num tip sınıfının bir üyesidir. f imzasını a -> a -> a (hiçbir kısıtlama olmadan) vermeye çalışırsanız, a tamamen sınırsız olduğu için işe yaramaz ve ne türler olabileceği hakkında hiçbir şey bilmiyoruz. Sonuç olarak, üzerinde (+) kullanamadık.

+0

+1! – CSnerd

0

Bir işlevin tip imzasındaki her bağımsız değişkenin türü boşluk içerebilir ve beyaz olmayan bir ayırıcı büyük olasılıkla zorunludur, dolayısıyla derleyici (ve insanlar!) Bunları birbirinden ayırt edebilir.

Örneğin, bir Parametrelenmiş soyut veri türü olabilir: Eğer değil' ise

myFunc :: MyType Int -> MyType Int -> String 

:

data MyType a = MyValue a 

ve (MyType tür kurucusu oluşturulmuştur) beton türleri alan bir fonksiyon argümanlar arasında -> var, imza

myFunc :: MyType Int MyType Int -> String -- Not valid code 

ve bir derleyicinin, işlevin gerçek argümanlarının ne anlama geldiğini anlamak için daha fazla sıkıntıları olacaktır (ve bazı durumlarda bunun imkansız olabileceğini merak ediyorum). En azından, daha az anlaşılabilir.

+0

Soruyu anladığından şüpheliyim. Haskell'in neden "A -> B -> C" yi "A B -> C" yerine kullanacağını soruyor. Yani: '-> 'nin solunda ne var argüman listesi ve sağda ne dönüş tipi var. – Shoe

+0

@Jeffrey Haklısın, bunu özledim. Cevabımı biraz değiştirdim. –

İlgili konular