このブログ記事では、Haskellの重要な型クラス、ファンクターを紹介します。

ファンクター (Functor) タイプクラス
Haskell の最も重要な概念の一つであり、多くの人が混乱するのがモナド (Monad) です。難しいのは、多くの人が急ぎすぎて、
できるだけ早く理解しようとするからです。ここでは、異なるアプローチを取り、モナドを真に理解するための前提条件をゆっくりと
確実に学んでいきます。その前提条件の一つがファンクターです。ファンクターは、ちょうど 1 つの型を持つ型コンストラクタに対して
適用できる型クラスです。型コンストラクタは、1 つ以上の型をパラメータとして取り、具体的な型を生成する関数です。以下は、
型コンストラクタ f
に対してファンクターのインスタンスを作成する方法です。
class Functor f where
fmap :: (a -> b) -> f a -> f b
型コンストラクタをファンクター型クラスの有効なインスタンスにするには、fmap
を定義するだけで良いです。
fmap
は、関数 (a -> b)
を取り、型コンストラクタ内の型の値に適用します。これは具体例がないと理解しづらいかもしれませんので、
いくつかの例を見てみましょう。
リスト
リストは、Int
、Float
、String
などの型を取り、新しい型 [Int]
、[Float]
、[String]
を生成する型コンストラクタです。
リストもファンクターであり、ファンクター型クラスの有効なインスタンスです。実際、map
はリストに対してのみ機能する fmap
です。
instance Functor [] where
fmap = map
map :: (a -> b) -> [a] -> [b]
map
関数は関数を取り、リスト内の要素に適用します。これは fmap
と同じことです。したがって、以下のようにすることができます。
ghci> map (*2) [1..3]
[2,4,6]
ghci> fmap (*2) [1..3]
[2,4,6]
ghci> map (++"!") ["Hello", "Nice to meet you"]
["Hello!","Nice to meet you!"]
ghci> fmap (++"!") ["Hello", "Nice to meet you"]
["Hello!","Nice to meet you!"]
Maybe
もう一つの型コンストラクタ/ファンクターの例は Maybe
で、Int
、Float
、String
などの型を取り、
新しい型 Maybe Int
、Maybe Float
、Maybe String
を生成します。以下は、Maybe
がファンクター型クラス
のインスタンスである方法です。
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
異なる値コンストラクタ Just
と Nothing
に対して fmap
を定義するためにパターンマッチングを使用しています。
Nothing
は空なので、出力も Nothing
になります。一方、Just
では中の値に関数 f
を適用します。
これにより、fmap
関数を Maybe
に対して使用して、以下のようにすることができます。
ghci> fmap (*2) (Just 4)
Just 8
ghci> fmap (*2) Nothing
Nothing
ghci> fmap (++"!") (Just "Hello")
"Hello!"
ghci> fmap (++"!") Nothing
Nothing
IO
IO
も実際には型コンストラクター/ファンクターであり、 (IO ()
, IO String
, IO Float
, etc.) 対応する fmap
関数があります。
instance Functor IO where
fmap f action = do
result <- action
return (f result)
これは IO アクションから値を result
にバインドし、関数 f
を result
に適用し、その値を持つ IO アクションを return
を使用して作成します。
したがって、以下のようにすることができます。
ghci> fmap (++"!") getLine
Hello
"Hello!"
上級者用チャレンジ: (->) r
もファンクターの有効なインスタンスです。fmap
がどのように定義されているかを考えてみてください。(ヒント: ->
は r -> a
のように型定義で使用され、2つの型をパラメータとして取り、関数の新しい型を生成する型コンストラクタでもあります。)
クイズ
この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。
リソース
- NA. Making Our Own Types and Typeclasses. Learn You a Haskell for Great Good.
- NA. Functors, Applicative Functors and Monoids. Learn You a Haskell for Great Good.