2012-06-28 12 views
17

Uważam, że pierwszeństwo i powiązanie jest dla mnie dużą przeszkodą w zrozumieniu, co gramatyka stara się wyrazić na pierwszy rzut oka do kodu haskell.Pierwszeństwo Haskell: Lambda i operator

Na przykład

blockyPlain :: Monad m => m t -> m t1 -> m (t, t1) 
blockyPlain xs ys = xs >>= \x -> ys >>= \y -> return (x, y) 

przez eksperyment, w końcu dostał to znaczy,

blockyPlain xs ys = xs >>= (\x -> (ys >>= (\y -> return (x, y)))) 

zamiast

blockyPlain xs ys = xs >>= (\x -> ys) >>= (\y -> return (x, y)) 

Który działa jako:

*Main> blockyPlain [1,2,3] [4,5,6] 
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] 

Mogę uzyskać informacje od ghci dla (>> =) jako operator, (infixl 1 >> =).

Ale nie ma informacji dla -> ponieważ nie jest operatorem.

Czy ktoś z was mógłby podać wzmiankę o tym, aby ułatwić zrozumienie tego gramatyka?

+0

Sieć [Haskell Report] (http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003) jest definitywnym odwołaniem do składni Haskella, chociaż być może gramatyka BNF jest nieco niskiego poziomu dla pytania, którym jesteś pytając ...? –

Odpowiedz

23

Zasada lambdas jest całkiem prosta: ciało lambda przebiega tak daleko w prawo, jak to możliwe, bez uderzania w niewyważone nawiasy.

f (\x -> foo (bar baz) *** quux >>= quuxbar) 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
         body 
+3

Co oznacza, że ​​obowiązuje jako ostatni. Oznacza to, że (->) ma niższy priorytet niż każdy inny operator. Sądzę, że to samo dotyczy 'do' i (<-), a także są one maksymalnie dokładne, stosują się jako ostatnie i mają niższy priorytet niż dowolny operator. –

+4

Naprawdę nie podoba mi się określenie "pierwszy" i "ostatni" dla prewendencji - myślę, że łączy ono grupę z porządkiem oceny. Jest to coś, o co napotykam w nauczaniu matematyki. Lubię "ciasno" i "luźno", myśląc, że operatorzy trzymają się swoich operandów. W każdym razie '->' nie jest tak naprawdę operatorem infiksowania, ponieważ nie łączy dwóch terminów; raczej lambda jest formą syntaktyczną wyrażenia. Dlatego nie odpowiedziałem w kategoriach operatorów. – luqui

+1

Oba punkty dobrze zrobione. "Pierwszy" i "ostatni" to wyrażenia używane w większości programów nauczania matematyki K-12 (i nie kilku), gdy mówią o kolejności operacji. Moją próbą było zastosowanie tych powszechnie używanych (choć mniej dokładnych) terminów do twojej bardzo trafnej odpowiedzi. –

7

Dobrą regułą wydaje się, że nigdy nie można dokonać operator niestandardowy, który ma pierwszeństwo w stosunku zbudowany w konstrukcji składniowych. Na przykład rozważyć następujący przykład:

if b then f *** x else f *** y 

Niezależnie od skojarzeń z ***, nikt nie spodziewałby się do wiąże jak:

(if b then f *** x else f) *** y 

Nie ma wiele konstrukcji składniowych w Haskell (do i case są trochę odmienny ponieważ składni układzie), lecz let może być stosowany, jako kolejny przykład:

(let x = y in y *** x) /= ((let x = y in y) *** x) 
+2

Z wyjątkiem aplikacji funkcji i aktualizacji rekordów ... – luqui