[英]Is there a non cyclic definition for `liftA2` and `<*>` on stackage.org
On stackage.org , the following cyclic declaration exists for liftA2
and <*>
for the Applicative
typeclass.在stackage.org 上,对于liftA2
和<*>
Applicative
类型类存在以下循环声明。
(<*>) = liftA2 id
liftA2 f x y = f <$> x <*> y
Is a non-cyclic declaration available for liftA2
or <*>
on the site.是一个可用于网站上的liftA2
或<*>
的非循环声明。 Are such completely cyclic references an oversight?这种完全循环的引用是一种疏忽吗?
UPDATE:更新:
The following (necessary) clarifying declarations seems to be missing from hoogle
docs: hoogle
文档中似乎缺少以下(必要的)澄清声明:
<*> :: Functor F => F (a -> b) -> F a -> F b
and by implication (due to cyclic declaration)并暗示(由于循环声明)
liftA2 :: Functor F => (a -> b -> c) -> F a -> F b -> F c
[…] the following cyclic definition exists for
liftA2
and<*>
for theApplicative
type class. […]Applicative
类型 class 的liftA2
和<*>
存在以下循环定义。(<*>) = liftA2 id liftA2 fxy = f <$> x <*> y
Is a non-cyclic definition available for
liftA2
or<*>
on the site.网站上的liftA2
或<*>
是可用的非循环定义。
These aren't definitions of the methods, exactly;确切地说,这些不是方法的定义; they're default definitions.它们是默认定义。 A typeclass with one parameter is just a set of types, and an instance
definition is the price of admission for membership in the set.具有一个参数的类型类只是一组类型,而instance
定义是该集合成员资格的入场费。 The Minimal
pragma for Applicative
tells you that you must implement one of these two methods, and that information is displayed in Haddock documentation. Applicative
的Minimal
pragma 告诉您必须实现这两种方法之一,并且该信息显示在 Haddock 文档中。
The actual definitions of liftA2
, <*>
, and pure
are specific to the instances of Applicative
. liftA2
、 <*>
和pure
的实际定义特定于Applicative
的实例。 Generally speaking, if a typeclass contains methods that can be implemented using only the other methods of the typeclass, then that method doesn't strictly need to be part of the class, since it could be a top-level definition with a constraint.一般来说,如果一个类型类包含可以仅使用该类型类的其他方法实现的方法,那么该方法不需要严格地成为 class 的一部分,因为它可以是具有约束的顶级定义。
However, such a method may be included anyway.然而,无论如何都可以包括这样的方法。 This may be just for convenience, when it's easier to define an instance in terms of one function even though it's not the “most fundamental” operation.这可能只是为了方便,因为它更容易根据 function 定义一个实例,即使它不是“最基本的”操作。 It's also often for performance reasons: redundant methods tend to be included when it's possible to implement a method more efficiently than the default for a particular type.这通常也是出于性能原因:当可以比特定类型的默认方法更有效地实现方法时,往往会包含冗余方法。 In this case, for example, liftA2
may be able to traverse two structures together more efficiently than traversing one with <$>
and then the other separately with <*>
.在这种情况下,例如, liftA2
可能能够更有效地一起遍历两个结构,而不是使用<$>
遍历一个结构,然后使用<*>
单独遍历另一个结构。
GHC also offers DefaultSignatures
as a way to add more specific defaults, typically defined in terms of Generic
, but this only lets you add typeclass constraints, largely for convenience with deriving
. GHC 还提供DefaultSignatures
作为添加更多特定默认值的一种方式,通常根据Generic
定义,但这仅允许您添加类型类约束,主要是为了方便deriving
。
Are such completely cyclic references an oversight?这种完全循环的引用是一种疏忽吗?
Not at all, they're intentional.一点也不,他们是故意的。 Cyclic definitions in default implementations of typeclass methods are quite common.类型类方法的默认实现中的循环定义非常普遍。 For example, Eq
is defined in the Haskell Report something like this:例如, Eq
在 Haskell 报告中定义如下:
class Eq a where
(==) :: a -> a -> Bool
x == y = not (x /= y)
(/=) :: a -> a -> Bool
x /= y = not (x == y)
It is possible to forget to implement one of these, so that they both use the default, and thus represent an infinite loop, however:可能会忘记实现其中之一,因此它们都使用默认值,因此代表一个无限循环,但是:
This generates a warning by default ( -Wmissing-methods
is enabled by -Wdefault
).默认情况下,这会生成一个警告( -Wmissing-methods
由-Wdefault
启用)。
If a Minimal
pragma is not specified, all of the methods in the class are assumed to be required.如果未指定Minimal
pragma,则假定 class 中的所有方法都是必需的。
So really the only other options in this case are to remove one or the other from the class, or omit providing a default for one of them.因此,在这种情况下,实际上唯一的其他选项是从 class 中删除一个或另一个,或者省略为其中一个提供默认值。 If you want to know about how these methods are implemented for Applicative
, the thing to look at is the instance
implementations for concrete type constructors like []
, ZipList
, Maybe
, StateT
, and so on.如果您想了解这些方法是如何为Applicative
实现的,那么要看的是具体类型构造函数的instance
实现,例如[]
、 ZipList
、 Maybe
、 StateT
等。
Is a non-cyclic definition available for liftA2? LiftA2 是否有非循环定义?
The implementations of (<*>)
and liftA2
are specific to the instances of the Applicative
typeclass. (<*>)
和liftA2
的实现特定于Applicative
类型类的实例。 Indeed, for each Applicative
instance you need to implement pure
, and (<*>)
or liftA2
, or as specified by the MINIMAL
pragma:实际上,对于每个Applicative
实例,您需要实现pure
和(<*>)
或liftA2
,或者由MINIMAL
pragma 指定:
class Functor f => Applicative f where {-# MINIMAL pure, ((<*>) | liftA2) #-} -- …
For example for the Maybe
instance of Applicative
, this is implemented as:例如,对于Applicative
的Maybe
实例,它被实现为:
instance Applicative Maybe where pure = Just Just f <*> m = fmap fm Nothing <*> _m = Nothing liftA2 f (Just x) (Just y) = Just (fxy) liftA2 _ _ _ = Nothing Just _m1 *> m2 = m2 Nothing *> _m2 = Nothing
Simply implementing pure
and (<*>)
would here be sufficient, since then liftA2
is implemented in terms of (<*>)
.在这里简单地实现pure
和(<*>)
就足够了,因为那时liftA2
是根据(<*>)
实现的。 It is however often more efficient to implement the other methods as well.然而,执行其他方法通常更有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.