21

優先順位と結合性は、文法がhaskellコードに一目で何を表現しようとしているのかを理解する上での大きな障害であることがわかりました。

例えば、

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

実験によって、私はついにそれが意味することを理解しました、

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

それ以外の

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

これは次のように機能します:

*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)]

ghciから(>> =)の情報を演算子として取得できます(infixl 1 >> =)。

ただし、演​​算子ではないため、->の情報はありません。

皆さんの誰かが、この文法を理解しやすくするための参考資料を教えてもらえますか?

4

2 に答える 2

26

ラムダのルールは非常に単純です。ラムダの本体は、不均衡な括弧にぶつかることなく、可能な限り右に拡張されます。

f (\x -> foo (bar baz) *** quux >>= quuxbar)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                       body
于 2012-06-28T02:54:45.390 に答える
7

経験則として、組み込みの構文構造よりも優先されるカスタム演算子を作成することはできないようです。たとえば、次の例を考えてみましょう。

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

の結合性に関係なく、誰もそれが次の***ようにバインドされることを期待しません。

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

Haskellには構文構造はあまりありませんが(doレイアウトcase構文のために少し特殊です)、let別の例として使用できます。

(let x = y in y *** x) /= ((let x = y in y) *** x) 
于 2012-06-28T12:17:18.507 に答える