2012-01-24 30 views
9

'daki sınırlayıcı değişkenleri referanslayan tümcenin, trapez kuralını kullanarak Haskell'deki bir işlevi sayısal olarak entegre etmeye çalışıyorum, entegre edilecek aralığın bitiş noktaları için argümanları a, b alan bir anti-türevi döndürüyorum. Yukarıda Haskell: lambda

integrate :: (Float -> Float) -> (Float -> Float -> Float) 

integrate f 
    = \ a b -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
     d = (b - a)/n 
     n = 1000 

, I Bu neredeyse lambda b, bir bağlı argümanlar haricinde, işler

n - for the number of subintervals 
d - for the width of each subinterval 

kullanın. Ben hata mesajı alıyorum:

Not in scope: `b' 
Not in scope: `a' 

Ben kapsamı b sadece bu lambda ifadesi sınırlı olduğunu anlayabiliyorum ama I (yazmak zorunda kalmamak için Haskell bir çözüm vardır Yukarıdaki her bir d için ba)/n?

+4

til: Sen 'kullanamazsınız where' lambdas ile [let vs nerede] (http://www.haskell.org/haskellwiki/Let_vs._Where). Ayrıca bakınız [nerede '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' (http://stackoverflow.com/questions/6032183/where-does-the-where-clause-come-in-handy-in-haskell) – rampion

+0

Cevaplayan herkese teşekkürler. Bu sorunun, tartışmanın nerede olduğu hakkında iyi bilinen bir izne doğrudan yol açtığının farkında değildim. Ben de şu fonksiyonu yazmamı önerenlere teşekkür etmek istiyorum: f a b = ... Bu hoş ve özlü bir çözümdür. – Bylextor

cevap

1

deneyin:

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
     d = (b - a)/n 
     n = 1000 
16

Sen iki Float s alır ve Float döndüren bir işlev dönmek gerekiyor düşünüyorsunuz ama aslında sizin integrate işlevinde iki ekstra Float argümansız ve kullanmanın farklı değil Körpe (yani sadece sağlanmayan ve dönüş tipi Float -> Float -> Float olacaktır).

Yani bunun

integrate :: (Float -> Float) -> Float -> Float -> Float 

integrate f a b 
    = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
     d = (b - a)/n 
     n = 1000 

gibi işlev yazabiliriz Yoksa where yerine let ... in kullanabilirsiniz:

integrate f 
    = \a b -> 
     let d = (b - a/n) 
      n = 1000 
     in d * sum [ f (a + d * k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
+2

FWIW, Matthew, parantezleri tip imzasında atladı, ancak bu gerekli değil. Tip imzasını aynı tutabilir ve fonksiyon gövdesini bu yeni şekilde yazabilirsiniz. İki imza, * tam * eşdeğerdir. – luqui

+0

Çok iyi tespit edildi. Cevabını yazarken unutmuş olmam gerektiğini söylemeyi düşünüyordum. –

+0

Teşekkürler. Fonksiyonu entegre olarak yeniden yazarak b = ... mükemmel bir çözümdür. – Bylextor

4

Tabi. nereye ısrar ederse

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
     d = (b - a)/n 
     n = 1000 
2

:

integrate f = \a b -> case() of 
    () -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
      where 
       d = (b - a)/n 
       n = 1000 

oldukça güzel görünüyor, değil mi? durum biraz daha motive görünmesi için:

integrate f = \a b -> case (f a + f b) of 
    fs -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * fs 
      where 
       d = (b - a)/n 
       n = 1000 
+0

Çok akıllı! Teşekkür ederim! – Bylextor

3

Sen çözüm yolları yer çok şey var.

Eğer lambda ifadeleri dışında herhangi bağlayıcı sözdizimi bilmiyorsanız size (çünkü onun teorik güzelliği en çok sevdiğim hangi ama asla nedeniyle sözdizimsel çirkinlik kullanın) yapabilirsiniz:

integrate f 
    = \a b -> (\d -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)) 
      ((b - a)/n) 
    where 
     n = 1000 

ise Eğer tanımları görmek ve sadece bunu yapabilirsiniz -syntax where biliyorum: Ayrıca let -Sözdizimi biliyorsanız

integrate f = go 
    where 
    n = 1000 
    go a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
     where 
     d = (b - a)/n 

, bunu yapabilirsiniz:

Eğer a -> (b -> c -> d) a -> b -> c -> d aynı olduğunu hatırlarsanız
integrate f = 
    \a b -> let d = (b - a)/n 
      in d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
    n = 1000 

Son olarak, bariz yapabilirsiniz:

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b) 
    where 
    n = 1000 
    d = (b - a)/n 
+1

İlk seçeneği kullanmamanın başka bir nedeni vardır: lambdaslar polimorfizme izin vermez. – luqui

+0

Teşekkür ederiz. İzin ver seçeneği, muhtemelen, değişken değişken sorunum için en basit çözümdür. – Bylextor

+0

Bana "git" hakkında biraz daha bahseder misin? Bunu araştırmaya çalıştım, ancak Haskell'de "git" hakkında herhangi bir bilgi bulmak çok zor çünkü arama motorları bunu her zamanki İngilizce kelime "go" ile karıştırıyor ve "go" çoğu kitap indeksinde görünmüyor. – Bylextor