2015-10-11 17 views
6

Ben şu işlevi tanımı yapmaya çalıştı AncakBu nokta neden ücretsiz tanım Haskell'de çalışmıyor?</p> <pre><code>relativelyPrime x y = gcd x y == 1 </code></pre> <p>noktası içermeyen:

relativelyPrime = (== 1) . gcd 

, bu bana aşağıdaki hata veriyor:

Couldn't match type ‘Bool’ with ‘a -> Bool’ 
Expected type: (a -> a) -> a -> Bool 
    Actual type: (a -> a) -> Bool 
Relevant bindings include 
    relativelyPrime :: a -> a -> Bool (bound at 1.hs:20:1) 
In the first argument of ‘(.)’, namely ‘(== 1)’ 
In the expression: (== 1) . gcd 
In an equation for ‘relativelyPrime’: 
    relativelyPrime = (== 1) . gcd 

yapmam oldukça anlama. gcd iki Ints/Integer alır, bir Ints/Integer döndürür, sonra Int/Integer eşittir '1' için kontrol edilir. Hatamın nerede olduğunu göremiyorum.

+4

iyi 'başka bir fonksiyon var üretecek gcd' sadece bir argüman verilirse - ve Noktadan içinde ücretsiz sürümü elinizde bu * function * 'da (== 1) 'hangi fonksiyonların nasıl ele alınacağını bilemezsiniz);) – Carsten

+2

belki ilk * ne zaman * anlayacağınızı anlarsınız * remove *: * relativePrime x = (= = 1). gcd x' bu işe yarıyor!o * * için 'gcd' oruç bağlı olarak Şimdi * kaldırmak *' artık x' olamaz - sen yaparsın (== 1) 'Carsten yorumuna @ $ gcd x' – Carsten

+1

doğrudur olsaydı. Bir seçenek, 'uncurry'yi' gcd'yi tek argüman fonksiyonuna çevirmek (iki tamsayıda bir tuple alarak) kullanmaktır. – psmears

cevap

7

gcd iki giriş gerektirir, çünkü işlev bileşimi yalnızca gcd bir girdi sağlar, çünkü çalışmaz. fonksiyon kompozisyonunun tanımını göz önünde bulundurun:

f . g = \x -> f (g x) 

Dolayısıyla, ifade (== 1) . gcd eşdeğerdir:

\x -> (== 1) (gcd x) 

İstediğin değil. Sen istiyorum:

\x y -> (== 1) (gcd x y) 

Bir ikili işlevi ile bir tekli fonksiyonunu oluşturmak için yeni bir operatöre tanımlayabiliriz:

f .: g = \x y -> f (g x y) 

Ardından, ifadesi olur: Aslında

relativelyPrime = (== 1) .: gcd 

, (.:) operatörü, işlev bileşimi açısından tanımlanabilir:

(.:) = (.) . (.) 

Bir baykuşa benziyor, ama gerçekten de eşdeğer. Böylece, başka bir yol ifadesini yazmak için:

relativelyPrime = ((== 1) .) . gcd 

Gördüğünüz sonra neler olduğunu anlamak istiyorsanız: What does (f .) . g mean in Haskell?

5

sen buna yorum olarak - Eğer gerçekten bir nokta-ücretsiz sürümü istiyorsanız öncelikle tek girişi kabul eden bir sürümü (tuple) içine gcd dönüştürmek için uncurry gcd kullanabilirsiniz: o görüşün

Prelude> :t uncurry gcd 
uncurry gcd :: Integral c => (c, c) -> c 

(== 1) ve orijinal imza için tekrar nihayet curry it: sadece ilk argüman verilirse

relativeelyPrime = curry ((== 1) . (uncurry gcd)) 

sürümü sadece gcd çünkü işe yaramadı bir fonksiyon üretir ve bu bir sayı bekleyen (== 1) için yasal bir giriş değildir.

İlgili konular