Haskell勉強会

関数型プログラミングの学習日記

Haskellの右結合と左結合

Haskellの勉強メモ。

 

haskell.hatenablog.com

 

(p.121) 関数の型

 

Haskellでは、演算子もまた関数です。

演算子に()(丸カッコ)を付けると、関数として扱えます。

まだ、:tでその型も確認できます。

Prelude> :t (&&)
(&&) :: Bool -> Bool -> Bool

->が2個も出てきました。

->自体は右結合になっています。

つまり、Bool -> Bool -> Boolという型に->の結合優先度に合わせて省略されているカッコをつけると、Bool -> (Bool -> Bool)という型と同じということになります。

これを->の表現通りに解釈するとき、「Bool型の値を受け取って、『Bool型の値を受け取って、Bool型の値になる』関数になる」関数ということになります。

論理積演算子(&&)は、Bool型の値を2つ(その演算子の両側に)受け取って、Bool型の値になるため、このようになります。

 

右結合とは?

演算子 右結合 左結合 - Google 検索

 

www.bohyoh.com

 

演算子の結合性とは何ですか。

演算子には、右結合性をもつものと左結合性をもつものとがあります。

 

2項演算子を○と表した場合、式a○b○cが

(a○b) ○ c     左結合

とみなされるのが左結合の演算子であり、

a ○ (b○c)     右結合

とみなされるのが右結合の演算子です。

 

すなわち、同じ優先度の演算子が並んでいるときに、左右どちらの演算が結び付けられるのかを示すのが結合性です。

 

たとえば、減算を行う2項-演算子は左結合ですから、

5 - 3 - 1  →  (5 - 3) - 1  /* 左結合 */

です。

もしも、右結合だったら、5 - (3 - 1)と解釈され、答えも違うものとなってしまいます。

 

代入を行う単純代入演算子=は右結合ですから、次のようになります。

a = b = 1  →  a = (b = 1)   /* 右結合 */

 

www.pandanoir.info

 

演算子の結合性とは

演算子がどっちからくっつくか、ということです。

 

例えば「・」という架空の演算子を考えます。

このとき・演算子は、A・B・C が

(A・B)・C と同じなら左結合性

A・(B・C)と同じなら右結合性

です。

 

同じ演算子が並んでいた場合、

  • 左側から計算していく演算子を「左結合」
  • 右側から計算していく演算子を「右結合」 

というのですね。

 

Haskell演算子の結合性

d.hatena.ne.jp

 

ghci で、":i 演算子" とすればわかるんですね。

省略しないなら ":info (演算子)" 。

infix は無結合、infixl は左結合、infixr は右結合。

レベルは 0 から 9 まで の 10 段階で、数が大きいほど結び付きが強いです。

 

Haskell演算子「&&」の結合性を調べてみます。

f:id:hamamuratakuo:20190119224355p:plain

 

Prelude> :i (&&)
(&&) :: Bool -> Bool -> Bool    -- Defined in ‘GHC.Classes’
infixr 3 &&

 

infixrは「右結合」だったので、「&&」は右結合になりますね。

 

Haskell演算子「->」の結合性を調べてみます。

f:id:hamamuratakuo:20190119202520p:plain

 

Prelude> :i (->)
data (->) (a :: TYPE q) (b :: TYPE r)   -- Defined in ‘GHC.Prim’
infixr 0 ->

 

infixrは「右結合」だったので、「->」も右結合になりますね。

優先順位(レベル)は「0」なので一番弱いみたいです。

(=数字が大きい方が、優先度=結び付きが強い。)

 

まとめ

  • 演算子「->」は右結合。
  • 「Bool -> Bool -> Bool」は「Bool -> (Bool -> Bool)」と同じ意味。
  • 演算子の結合性や優先順位が分からない場合、「:i」コマンドで調べられる。