これは、ユーザーが速度に合わせてカスタマイズできるようにするためのメンバーとして含まれています。これは、と一貫性があるためだと思い>>
ます。
リーダーモナドの場合はもっと速いかもしれないと思います((->) r)
。
x <$ _ = const x
vs
x <$ fa = fmap (const x) fa = (const x) . fa
ただし、これは実際にはコンパイラの最適化の問題です。そして、それはベースのリーダーモナドに対して定義されていないようです。
また、厳密なコレクションのパフォーマンスが向上する可能性があります。つまり、
data Strict a = Strict !a
instance Functor Strict where
fmap f (Strict a) = Strict (f a)
x <$ _ = Strict x
これはファンクターの法則には従いませんが、それでも、状況によってはこれを実行したい場合があります。
3番目の例は、無限のコレクションからのものです。無限のリストを検討する
data Long a = Cons a (Long a)
instance Functor Long where
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
これは問題なく動作しますが、考えてみてください
countUpFrom x = Cons x (countUpFrom (x+1))
ones = 1 <$ (countUpFrom 0)
今、私たちの定義で
ones = 1 <$ (countUpFrom 0)
= fmap (const 1) (countUpFrom 0)
= Cons (const 1 0) (fmap (const 1) (countUpFrom 1)
= Cons (const 1 0) (Cons (const 1 1) (fmap (const 1) (countUpFrom 2))
つまり、Cons
このリストをたどると、大量のセルが割り当てられます。一方、あなたが定義した場合
x <$ _ = let xs = Cons x xs in xs
よりも
ones = 1 <$ countUpFrom 0
= let xs = Cons 1 xs in xs
結び目を結びました。さらに極端な例には、無限の木があります
data ITree a = ITree a (ITree a) (ITree a)