このブログ記事では、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.