如何解决将两者都理解为函子
看看Either是如何定义为函子的,我可以看到
derive instance functorEither :: Functor (Either a)
这对我来说是“你可以map
一个Either,只要你可以map
它的元素。
但两者都不是只有一个元素。如果没有 derive
,这将如何实现?这是我尝试过的:
data Either a b = Left a | Right b
instance functorEither :: Functor (Either a)
where
map f (Right b) = Right $ f b
map _ a = a
当然,这些类型在这里不起作用:
右边有这个签名:map :: forall a b. (a -> b) -> f a -> f b
然而,左派不行:map :: forall a b. (a -> b) -> f a -> f a
我的部分直觉是说 Either a b
不是函子,只有 Either a
是函子。这就是为什么 map
在 Right
上工作而忽略 Left
这并没有真正让我对它是如何实现的有任何直觉。我仍然需要一种匹配两个构造函数的方法,不是吗?
另一方面,我认为用 map
替换内部函数的 identity
实现在技术上对函子来说是守法的吗?无视构图法则就满足了?
解决方法
虽然您提议的 Functor
实例定义确实无法编译,但不是因为您所说的原因。而且它也“基本上”是正确的,只是没有以令编译器满意的方式编写。
为了方便起见,这里又是您的定义:
data Either a b = Left a | Right b
instance functorEither :: Functor (Either a)
where
map f (Right b) = Right $ f b
map _ a = a
这是您在尝试编译时遇到的实际错误:
Could not match type
a02
with type
b1
while trying to match type Either a0 a02
with type Either a0 b1
while checking that expression a
has type Either a0 b1
in value declaration functorEither
where a0 is a rigid type variable
bound at (line 0,column 0 - line 0,column 0)
b1 is a rigid type variable
bound at (line 0,column 0)
a02 is a rigid type variable
bound at (line 0,column 0)
我承认这有点难以解释,如果您没有预料到的话。但它与map
的Either a
需要具有类型forall b c. (b -> c) -> Either a b -> Either a c
的事实有关。所以 a
左边的 map _ a = a
类型为 Either a b
,而右边的 Either a c
类型为 b
- 这些是不同的类型(通常),因为 {{ 1}} 和 c
可以是任何值,因此您不能使用相同的变量 a
来表示每种类型的值。
(This 问题,虽然是关于 Haskell 而不是 Purescript,但更深入地解释了这个错误。)
要修复它,如上述问题中所暗示的,您必须明确提及您映射的值是 Left
值:
data Either a b = Left a | Right b
instance functorEither :: Functor (Either a)
where
map f (Right b) = Right $ f b
map _ (Left a) = Left a
这很好,因为 Left a
可以在左侧解释为 Either a b
类型,在右侧解释为 Either a c
。
至于实例“做什么”:您是正确的,“要么 ab 不是函子,要么 a 是函子”——因为函子必须采用一个类型变量,Either a
这样做但Either a b
没有。是的,因为在 Either a b
和 Either a c
之间实际“变化”的类型变量是在 Right
中使用的类型变量,map
只能映射到 {{1 }} 值,并保留 Right
值 - 这是唯一能够满足所需类型的东西。
Left
通常被解释为表示计算结果,其中 Either a b
值表示失败,而 Left
值表示成功。从这个意义上说,它是 Right
的一个稍微“扩展”的版本 - 不同之处在于,不是由单个值 (Maybe
) 表示失败,而是您获得一条数据({{1} } 输入 Nothing
),它可以告诉您有关错误的信息。但是 a
实例的工作方式与 Either a b
的相同:它映射任何成功,而不管失败。
(但是没有合乎逻辑的理由为什么您不能“映射”Functor
值。Bifunctor 类是 {{1}可以做到这一点。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。