一言で言うと、a
は「関数の戻り値」です。
((->) r)
は(+ 3)
のように、関数型を表す演算子->
の左辺(第1型引数)にr
という型変数を適用したものを表しています。
->
の左辺は関数の引数の型を表していて、もう一つの引数である右辺は関数の戻り値の型を表しているのでした。
なので、例えば((->) r a)
という型はr -> a
と等価で、「r
を受け取ってa
を返す関数」を表していますし、((->) Int Bool)
という型はInt -> Bool
と等価で「Int
を受け取ってBool
を返す関数」を表しています。
従って、((->) r)
は「->
に対して、引数の型r
のみを適用した型」であり、それをMonad
やFunctor
におけるm
やf
として扱うと、m a
は((->) r a)
、すなわち「r
を受け取ってa
を返す関数」と置き換えられることになります。
つまりa
はやっぱり「戻り値の型」なんですね。
やや長くなったので一旦割愛しますが、h >>= f = \w -> f (h w) w
という(>>=)
の実装における各式の型を詳細に見ても、関数モナドにおけるm a
のa
が関数の戻り値となっていることがわかるはずです。
ちなみに、((->) r a)
がr -> a
と等価であることを確かめるには、GHCiに下記のように入力して、id
など適当な関数に対して((->) a a)
という型注釈を付けてみるといいでしょう。
haskell
1> :t id :: ((->) a a)
2id :: ((->) a a) :: a -> a
さらに、敢えて間違った型注釈を付けてみると、((->) a b)
という表記が関数型として認識されているのがよくわかるかと思います。
haskell
1> :t id :: ((->) a b)
2
3<interactive>:1:1: error:
4 • Couldn't match type ‘a1’ with ‘b1’
5 ‘a1’ is a rigid type variable bound by
6 an expression type signature:
7 forall a1 b1. a1 -> b1
8 at <interactive>:1:7-16
9 ‘b1’ is a rigid type variable bound by
10 an expression type signature:
11 forall a1 b1. a1 -> b1
12 at <interactive>:1:7-16
13 Expected type: a1 -> b1
14 Actual type: b1 -> b1
15 • In the expression: id :: ((->) a b)
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/09 01:00
2019/03/10 00:39
2019/03/10 02:27