简体   繁体   English

为什么`((,)r)`一个非适用的Functor?

[英]Why is `((,) r)` a Functor that is NOT an Applicative?

From functors that are not applicatives : 来自不适用的仿函数

A type constructor which is a Functor but not an Applicative. 一个类型构造函数,它是一个Functor但不是Applicative。 A simple example is a pair: 一个简单的例子是一对:

 instance Functor ((,) r) where fmap f (x,y) = (x, fy) 

But there is no way how to define its Applicative instance without imposing additional restrictions on r . 但是如果不对r施加额外的限制,如何定义其Applicative实例是没有办法的。 In particular, there is no way how to define pure :: a -> (r, a) for an arbitrary r . 特别是,如何为任意r定义pure :: a -> (r, a)

Question 1: Why is this so? 问题1:为什么会这样? Here is how pure could work with functions f of type a -> b : 以下是pure可以使用类型a -> b函数f

(pure f) (pure x, pure y) = (pure x, pure f y)

From there, the definition of pure :: a -> (r, a) could depend on what r is. 从那里, pure :: a -> (r, a)可能取决于r是什么。 For example, if r is Integer , then you could define 例如,如果rInteger ,那么您可以定义

pure x = (0 :: Integer, x)

in your instance declaration. 在您的实例声明中。 So what is the issue? 那么问题是什么?

Question 2: Can we say in general that if F is a functor, then <*> can always be defined, but pure might not always be defined? 问题2:一般来说,如果F是一个仿函数,那么总是可以定义<*> ,但是可能并不总是定义pure吗?

Suppose we have 假设我们有

pure :: forall r a. a -> (r, a)

then, in particular, we have 那么,特别是我们有

magic :: forall r. r
magic = fst (pure ())

Now, we can specialise the type variable r to get 现在,我们可以专门化类型变量r来获取

magic :: Void

where Void is the datatype with no constructors, which means 其中Void是没有构造函数的数据类型,这意味着

magic = undefined

but as type variables (and the types which specialise them) play no run time role, that means magic is always undefined. 但是作为类型变量(以及专门化它们的类型)不会发挥运行时角色,这意味着magic 总是未定义的。

We've discovered that ((,) r) can be Applicative only for inhabited r . 我们发现, ((,) r)可以是Applicative仅适用于居住 r And there's more. 而且还有更多。 With any such instance, we can write 对于任何这样的实例,我们都可以写

munge :: r -> r -> r
munge r0 r1 = fst ( pure (\ _ _ -> ()) <*> (r0, ()) <*> (r1, ()) )

to define a binary operator on r . r上定义二元运算符。 The Applicative laws tell us effectively that munge must be an associative operator that absorbs magic on either side. Applicative法则有效地告诉我们, munge必须是一个吸收任何一方magic的联想算子。

That's to say there is a sensible instance 这是说一个明智的实例

instance Monoid r => Applicative ((,) r) where
  pure a              = (mempty, a)
  (r0, f) <*> (r1, s) = (mappend r0 r1, f s)

(exactly what you get when you take pure=return; (<*>)=ap from the Monad (Writer r) ). (正是你从Monad (Writer r)获取pure=return; (<*>)=ap得到的结果)。

Of course, some pedants would argue that it is legal (if unhelpful) to define 当然,一些学者会认为定义是合法的(如果没有帮助)

instance Monoid r where
  mempty = undefined
  mappend _ _ = undefined
  -- Monoid laws clearly hold

but I would argue that any sensible type class instance should contribute nontrivially to the defined fragment of the language. 但我认为任何明智的类型类实例都应该对语言的已定义片段做出非常重要的贡献。

Answer 1: 答案1:

 (pure f) (pure x, pure y) = (pure x, pure fy) 

I don't understand what you mean by this line. 我不明白你的意思。 It looks like nonsense: pure f would be a pair, and you can't apply a pair as if it were a function. 它看起来像废话: pure f将是一对,你不能应用一对,就好像它是一个函数。

From there, the definition of pure :: a -> (r, a) could depend on what r is. 从那里, pure :: a -> (r, a)可能取决于r是什么。

That is exactly the problem. 这正是问题所在。 r is fully general; r完全一般; the instance declaration says ((,) r) is a Functor for all types r . 实例声明说((,) r)所有类型r的Functor。 That means you have to somehow implement a single pure :: a -> (r, a) that works with any type r that a caller might choose. 这意味着你必须以某种方式实行单一pure :: a -> (r, a)与任何类型的作品r呼叫者可以选择。 This is impossible because there is no way to conjure up an arbitrary r from thin air. 这是不可能的,因为没有办法从稀薄的空气中召唤出任意的r

Or as your quote says: 或者如你的引言所说:

In particular, there is no way how to define pure :: a -> (r, a) for an arbitrary r . 特别是,如何为任意r定义pure :: a -> (r, a)

If you try to do something like 如果你尝试做类似的事情

pure x = (0 :: Integer, x)

you get an error: 你收到一个错误:

Couldn't match expected type ‘r’ with actual type ‘Integer’
  ‘r’ is a rigid type variable bound by
      the instance declaration
      at ...

Answer 2: 答案2:

What would <*> look like for pairs? <*>会是什么样的? It would be a function like 这将是一个功能

(<*>) :: (r, a -> b) -> (r, a) -> (r, b)
(r1, f) (r2, x) = (???, f x)

But what do you do with the ??? 但你怎么处理??? part? 部分? You have to put a value of r there, and fortunately you have some of those available ( r1 , r2 ). 你必须在那里放一个r值,幸运的是你有一些可用的( r1r2 )。 The problem is that (for arbitrary r ) there is no general way to combine two values, so you have to pick one of them. 问题是(对于任意r )没有通用的方法来组合两个值,所以你必须选择其中一个。

That's where you run into trouble with the laws: 这就是你遇到法律问题的地方:

pure id <*> v = v

This law says we have to pick r2 to preserve v . 这项法律规定我们必须选择r2来保护v

u <*> pure y = pure ($ y) <*> u

Since we have to pick r2 in <*> , the right-hand side of this law says the result will contain the r part of u . 由于我们必须在<*>选择r2 ,因此该法律的右侧表示结果将包含ur部分。 But that clashes with the left-hand side, which says that we get whatever r was returned by pure y . 但是,与左侧,它说,我们得到什么冲突r被返回pure y ( u is a completely arbitrary pair so there's no way a fixed value returned by pure is always going to match it.) u是一个完全任意的对,所以pure返回固定值总是不会匹配它。)

So we have a contradiction, meaning we can't even define <*> for ((,) r) . 所以我们有一个矛盾,这意味着我们甚至不能为((,) r)定义<*> Therefore the answer to your second question is "no". 因此,你的第二个问题的答案是“不”。


That said, there is a standard Applicative instance for pairs but it requires r to be a Monoid : 也就是说,对象有一个标准的Applicative实例,但它需要rMonoid

instance (Monoid r) => Applicative ((,) r) where
    pure x = (mempty, x)
    (r1, f) (r2, x) = (mappend r1 r2, f x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM