它作为一个成员包含在允许用户自定义它的速度,我猜是因为它使它与>> 一致。
我认为在 reader monad ((->) r) 的情况下它可能会更快。
x <$ _ = const x
对
x <$ fa = fmap (const x) fa = (const x) . fa
虽然,这确实是编译器优化的问题。而且,它似乎没有为 base 中的 reader monad 定义。
这也可能导致严格集合的性能提升。即
data Strict a = Strict !a
instance Functor Strict where
fmap f (Strict a) = Strict (f a)
x <$ _ = Strict x
这不符合函子定律,但在某些情况下,您可能希望这样做。
第三个例子来自无限集合。考虑无限列表
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)