Either和Either Int有什么区别?什么是A?多态类型构造函数?它的目的是什么?

时间:2014-04-23 09:23:27

标签: haskell polymorphism functor type-constructor

简介

我理解Maybe aMaybe Int之间的区别,我也理解Either a bEither Int Int之间的区别。我也理解Either IntMaybe是同一种动物,它们都将一个类型作为参数并生成一个新类型,即它们都是类型构造函数,它们将一个类型作为参数(或者具体如Int或不具体如a),并产生具体类型或多态类型。

现在我不明白的是Either a是什么类型的结构?它不像Maybe,因为如果我们向它提供具体类型(如Int),它就永远不会产生具体的(读取非多态)类型。所以在这种情况下,调用Either a多态类型构造函数并调用Maybe具体类型构造函数是正确的吗? (这就是我如何称呼它们,它们在Haskell命名法中的正式名称是什么?)

此外,我不知道像Either a这样的类型构造函数的Haskell类型系统中的官方分类是什么,因为它不能与Maybe属于同一类别,因为 - 如上所述上一段 - 无论我们应用什么类型Either a,结果类型永远不会是具体类型,即它始终是多态类型,例如Either a Int

我之所以这样问是因为Either aFunctor。这开始变得令人困惑。没有像我以前见过的任何东西。我不知道我应该如何在概念上解释Either a(多态类型构造函数)是Functor的实例这一事实?同样,(->) r(也是与Either a相同的动物)也是Functor

问题:

什么是Either a(->) r

他们正式称什么?

它们如何在概念上适合Haskell的类型系统?

这些多态类型构造函数在哪里更详细地描述/讨论?

我读到了什么,所以我对它们有了更好的理解?

我应该阅读有关种类的内容吗?类型是理解像Either a(->) r这样的多态类型构造函数的秘密方式吗?

Either a Int[a]是同一种动物吗?

Either a Int的唯一目的是为函数声明多态输入和输出类型,就像[a]fmap :: (a -> b) -> [a] -> [b]的情况一样?

最重要的问题

我应该如何根据上述想法解释以下代码?

instance Functor (Either a) where 
  fmap f (Right x) = Right (f x) 
  fmap f (Left x) = Left x

class Functor f where 
  fmap :: (a -> b) -> f a -> f b

结果fmap函数(类型为fmap :: (a -> b) -> Either c a -> Either c b)在c中会是多态的吗?

这是使Either a成为Functor个实例的唯一效果吗? 因此,fmap生成的c函数将是多态的?

相比,例如,将Either Int设为Functor的实例?

然后生成的fmap仅适用于Either Int a类型,但在所有Either a b类型上不能正常/多态地工作?

如果我理解正确这是拥有像Either a这样的多态类型构造函数的唯一目的和目的吗?那么fmap适用于所有Either a b类型?

我很困惑,我不确定我是否正确解释Either a。有人可以确认1)我的解释是正确的2)如果没有那么请赐教我。

感谢阅读。

3 个答案:

答案 0 :(得分:11)

Either a实际上并没有这样的事情。与多态函数一样,多态实例应该通过通用量化来读取系统-F样式:

forall a . instance Functor (Either a) where ...

仿函数实例本身是一个字典,即类型级函数

functor = Λf -> { Λa b -> (a->b) -> f a->f b }

所以这两个实例都会像

eitherFunctor = Λa -> functor (Either a)

或者,您可以将其视为编译器将instance Functor (Either a)替换为大量离散实例

instance Functor (Either ()) where ...
instance Functor (Either Int) where ...
...
instance Functor (Either (Either Int String)) where ...
...

虽然显然不可能这样做,但字面上。

答案 1 :(得分:1)

我不知道你的一些问题的答案 - 比如,某些事情被正式称为什么,或者在哪里阅读它们,因为在学习类型系统后它们对我来说是不言而喻的。 (这不应被视为一种建议,唯一的方法是获得研究依赖类型系统。)

Either Int也可以声明为Functor,但我们可以表达一个更一般的陈述,Either的第一个参数是{{Int实际上并不重要{1}} - 因此,我们声明Either aFunctor

在其他类型的系统中,无需区分kinds,而Either也可以被视为一种类型;但是在Haskell中,它们与类型分开处理以简化类型系统。 Kinds是一种描述类型具有arity并通过仅区分arity来避免依赖类型的复杂化的方法。因此,Either(->)有2个,或kind *->*->*

Either a Int[a]的动物相同,因为它们的种类为*

事实上,{p> fmap :: (a->b) -> Either c a -> Either c bc中是多态的。此声明的重要性在于保留 c。当然,对于任何类型c,唯一的方法就是Left x保持不变。

答案 2 :(得分:1)

Maybe不是一种类型。 Maybe Int是一种类型。但Maybe本身就是你可以制作出类型的东西。它是类型的构造函数

Either不是类型,它是一个类型构造函数。你知道如何理解Haskell函数吗?好吧,你也可以讨论类型构造函数。所以Either是一个2参数类型的构造函数,但Either Int是一个1参数类型的构造函数。而Either Int Bool是一种实际类型。

Functor类型类是更高级的类型类Show之类的内容适用于类型; Functor适用于类型构造函数。例如,你不写

instance Functor (Maybe Int) where ...

相反,你写了

instance Functor (Maybe) where ...

Functor的定义是

class Functor f where
  fmap :: (x -> y) -> f x -> f y

此处f不是类型,而是1参数类型构造函数。你给它一个参数(比如xy)来构造一个真实的,可用的类型。

值包含“类型”。类型签名中的东西有“种类”。 “类型”有类*。 “1参数类型构造函数”具有种类“* - > *”。它基本上说明了为获得实际类型需要提供多少参数。

总之,您可以Functor (Either Int)编写实例。但那时只允许Int;通过使它成为一个类型变量,你可以使它更具多态性。

请注意,如果你想要它,那么Either第二个参数是固定的而不是第一个...你不能这样做。从某种意义上说,更高级的类型类别有点像kludge。它们很容易理解,它们适用于简单的案例。功能依赖关系和关联类型是两种(不兼容)尝试更好地解决此问题。