在类型构造函数中部分应用类型

mel*_*ton 4 haskell

在"了解你一个Haskell"一书中,第11章我们介绍了newtype关键字,这一切对我来说都是有意义的,我们看到将Pair类型作为Functor的一个实例.

本讨论以一个问题陈述开始,即"只有一个参数的类型构造函数可以成为Functor的一个实例".我不明白这个说法.这个限制在哪里描述过?

在讨论的上下文中,我们有一个类型对定义为:

newtype Pair b a = Pair { getPair :: (a,b) }
Run Code Online (Sandbox Code Playgroud)

鉴于此,我本以为我们可以使用类似的东西:

instance Functor (Pair a b) where ...
Run Code Online (Sandbox Code Playgroud)

我原以为(Pair ab)会在Functor的定义中替换'f'而没有任何问题.什么阻止这种工作?

接下来,作者继续使用以下方法使Pair成为Functor的实例:

instance Functor (Pair c) where ...
Run Code Online (Sandbox Code Playgroud)

这是我迷路的地方.我不记得曾经在类型构造函数中看到"部分应用"类型.我不确定在这种情况下这甚至意味着什么,更不用说它如何解决上面提到的问题.

我想我在某个地方有一种误解,但我不知道该去哪里寻找它.我确实找到了这个答案,但它似乎只是回答这个问题的一部分.

Dan*_*ner 7

"只有一个参数的类型构造函数才能成为Functor的一个实例." 我不明白这个说法.这个限制在哪里描述过?

限制来自fmap定义中的类型Functor:

class Functor f where
    fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

由于类变量f应用于一个参数f a,因此用于实例化的类型Functor必须能够采用一个参数.由于应用程序f a是函数类型的一部分,f因此不能使用多个参数.(还有一个更微妙的部分是关于f在这里指定了什么类型的参数,但我认为现在值得跳过它;希望你的教程稍后会触及这个细微之处.)

鉴于此,我本以为我们可以使用类似的东西:

instance Functor (Pair a b) where ...
Run Code Online (Sandbox Code Playgroud)

我原以为(Pair ab)会在Functor的定义中替换'f'而没有任何问题.什么阻止这种工作?

它再次成为fmap阻止这种工作的类型.填补Pair c df(修改a,以cbd避免名称冲突),我们会得到

fmap :: (a -> b) -> Pair c d a -> Pair c d b
Run Code Online (Sandbox Code Playgroud)

这没有多大意义.

这是我迷路的地方.我不记得曾经在类型构造函数中看到"部分应用"类型.

嗯......现在你有了.=)

我不确定在这种情况下这甚至意味着什么,更不用说它如何解决上面提到的问题.

这意味着在术语级别的部分应用程序基本相同:Pair a类似于将另一种类型作为参数的类型函数.因此,例如,Pair a应用于Int给出Pair a Int类型.它解决了这个问题,因为现在我们提供了一个"类型函数"的东西,而不是"类型"的东西,所以将它应用到另一种类型是有道理的; 即,取代类型fmap为一个Pair c实例将是

fmap :: (a -> b) -> Pair c a -> Pair c b
Run Code Online (Sandbox Code Playgroud)

现在有意义,因为Pair c a并且Pair c b是明智的类型,而之前Pair c d aPair c d b过度应用,因此不是明智的类型.

  • 谢谢,丹尼尔。这有助于使其更清晰。盯着这本书看了一会儿后,我开始认识到“Functor”实例定义中“Pair c”和“Maybe”之间的相似之处。我之前从未想过“Maybe”定义案例中缺少的类型(“instance Functor Maybe ...”而不是“instance Functor (Maybe a) ...”)。它从来没有突然出现在我面前,所以我完全错过了那里发生的事情。现在我看到它了,我发现“也许”的实例定义_已经是_类型的部分应用。 (2认同)