繁体   English   中英

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

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

来自不适用的仿函数

一个类型构造函数,它是一个Functor但不是Applicative。 一个简单的例子是一对:

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

但是如果不对r施加额外的限制,如何定义其Applicative实例是没有办法的。 特别是,如何为任意r定义pure :: a -> (r, a)

问题1:为什么会这样? 以下是pure可以使用类型a -> b函数f

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

从那里, pure :: a -> (r, a)可能取决于r是什么。 例如,如果rInteger ,那么您可以定义

pure x = (0 :: Integer, x)

在您的实例声明中。 那么问题是什么?

问题2:一般来说,如果F是一个仿函数,那么总是可以定义<*> ,但是可能并不总是定义pure吗?

假设我们有

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

那么,特别是我们有

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

现在,我们可以专门化类型变量r来获取

magic :: Void

其中Void是没有构造函数的数据类型,这意味着

magic = undefined

但是作为类型变量(以及专门化它们的类型)不会发挥运行时角色,这意味着magic 总是未定义的。

我们发现, ((,) r)可以是Applicative仅适用于居住 r 而且还有更多。 对于任何这样的实例,我们都可以写

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

r上定义二元运算符。 Applicative法则有效地告诉我们, munge必须是一个吸收任何一方magic的联想算子。

这是说一个明智的实例

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

(正是你从Monad (Writer r)获取pure=return; (<*>)=ap得到的结果)。

当然,一些学者会认为定义是合法的(如果没有帮助)

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

但我认为任何明智的类型类实例都应该对语言的已定义片段做出非常重要的贡献。

答案1:

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

我不明白你的意思。 它看起来像废话: pure f将是一对,你不能应用一对,就好像它是一个函数。

从那里, pure :: a -> (r, a)可能取决于r是什么。

这正是问题所在。 r完全一般; 实例声明说((,) r)所有类型r的Functor。 这意味着你必须以某种方式实行单一pure :: a -> (r, a)与任何类型的作品r呼叫者可以选择。 这是不可能的,因为没有办法从稀薄的空气中召唤出任意的r

或者如你的引言所说:

特别是,如何为任意r定义pure :: a -> (r, a)

如果你尝试做类似的事情

pure x = (0 :: Integer, x)

你收到一个错误:

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

答案2:

<*>会是什么样的? 这将是一个功能

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

但你怎么处理??? 部分? 你必须在那里放一个r值,幸运的是你有一些可用的( r1r2 )。 问题是(对于任意r )没有通用的方法来组合两个值,所以你必须选择其中一个。

这就是你遇到法律问题的地方:

pure id <*> v = v

这项法律规定我们必须选择r2来保护v

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

由于我们必须在<*>选择r2 ,因此该法律的右侧表示结果将包含ur部分。 但是,与左侧,它说,我们得到什么冲突r被返回pure y u是一个完全任意的对,所以pure返回固定值总是不会匹配它。)

所以我们有一个矛盾,这意味着我们甚至不能为((,) r)定义<*> 因此,你的第二个问题的答案是“不”。


也就是说,对象有一个标准的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