我查看了实现,这更加神秘:
-- | Sequence actions, discarding the value of the first argument.
(*>) :: f a -> f b -> f b
a1 *> a2 = (id <$ a1) <*> a2
-- This is essentially the same as liftA2 (flip const), but if the
-- Functor instance has an optimized (<$), it may be better to use
-- that instead. Before liftA2 became a method, this definition
-- was strictly better, but now it depends on the functor. For a
-- functor supporting a sharing-enhancing (<$), this definition
-- may reduce allocation by preventing a1 from ever being fully
-- realized. In an implementation with a boring (<$) but an optimizing
-- liftA2, it would likely be better to define (*>) using liftA2.
-- | Sequence actions, discarding the value of the second argument.
(<*) :: f a -> f b -> f a
(<*) = liftA2 const
我甚至不明白为什么<$
应该在类型类中占有一席之地。看起来有fmap . const
可能没有的共享增强效应,a1
可能没有“完全实现”。这与Applicative
排序操作符的含义有什么关系?
答案 0 :(得分:7)
这些操作符对两个应用操作进行排序,并提供箭头指向的操作结果。例如,
> Just 1 *> Just 2
Just 2
> Just 1 <* Just 2
Just 1
编写解析器组合器的另一个例子是
brackets p = char '(' *> p <* char ')'
将是一个与括号中包含的p
匹配的解析器,并提供解析p
的结果。
实际上,(*>)
与(>>)
相同,但只需要Applicative
约束而不是Monad
约束。
我甚至不明白为什么
<$
应该在类型类中占有一席之地。
答案由the Functor documentation给出:(<$)
有时可以提供比默认值更高效的实现,即fmap . const
。
这与Applicative测序运算符的含义有何关系?
如果(<$)
效率更高,您希望在(*>)
的定义中保持这种效率。