fmap
(メソッドの) 型シグネチャFunctor
を例に挙げます。
(a -> b) -> f a -> f b
これは次の型シグネチャとどう違うのでしょうか?
a -> b -> f a -> f b
これら 2 つのタイプ署名には違いがあるのでしょうか?
ベストアンサー1
はい、違いはあります。型->
コンストラクタは右結合。 言い換えると、
a -> b -> f a -> f b
は以下と同等である
a -> (b -> (f a -> f b))
この型シグネチャは、 型のパラメータを受け取ってa
関数を返す関数を表します。この関数自体も 型のパラメータを受け取って関数をb
返します。この関数自体も 型のパラメータを受け取っf a
て 型の値を返しますf b
。
一方で、
(a -> b) -> f a -> f b
は、型のパラメータを受け取る関数a -> b
(つまり、型のパラメータを受け取りa
、型の値を返す関数b
)を表し、それ自体が型のパラメータを受け取りf a
、型の値を返す関数を返しますf b
。
以下は、2 つの型シグネチャの違いを示す、架空の例です。
f :: (Int -> Bool) -> [Int] -> [Bool]
f = map
g :: Int -> Bool -> [Int] -> [Bool]
g n b = map (\n' -> (n' == n) == b)
λ> let ns = [42, 13, 42, 17]
λ> f (== 42) ns
[True,False,True,False]
λ> g 42 True ns
[True,False,True,False]
λ> g 42 False ns
[False,True,False,True]