简体   繁体   English

Control.Lens中的“非法多态或限定类型”

[英]“Illegal polymorphic or qualified type” in Control.Lens

I'm working with Control.Lens . 我正在使用Control.Lens The actual function I'm writing is rather complex, but for the purpose of this question, I've boiled it down to a minimal failing example: 我写的实际功能相当复杂,但为了这个问题的目的,我把它归结为一个最小的失败例子:

import Control.Lens    

exampleFunc :: Lens s t a b -> String
exampleFunc _ = "Example"

This fails to compile, yielding the following error message: 这无法编译,产生以下错误消息:

Illegal polymorphic or qualified type: Lens s t a b
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `exampleFunc':
  exampleFunc :: Lens s t a b -> String

Why is this illegal? 为什么这是非法的? It seems awfully similar to the following, which does compile: 这似乎非常类似于以下,这确实编译:

import Data.Maybe

exampleFunc' :: Maybe (s, t, a, b) -> String
exampleFunc' _ = "Example"

So I'm assuming the difference lies in the definition of Lens . 所以我假设差异在于Lens的定义。 But what about the Lens type makes exampleFunc 's type illegal? 但是Lens类型如何使exampleFunc的类型非法? I have a sneaking suspicion it has to do with the Functor qualification in the definition of Lens , but I could be wrong. 我怀疑它与Lens定义中的Functor资格有关,但我可能错了。 For reference, the definition of Lens is: 作为参考, Lens定义是:

type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t

So, do I have to somehow satisfy the Functor qualification in my definition of exampleFunc ? 那么,我是否必须在我的exampleFunc定义中以某种方式满足Functor资格? If so, how? 如果是这样,怎么样? I'm not seeing where in my type signature I have the opportunity to declare this constraint. 我没有看到我的类型签名在哪里,我有机会宣布这个约束。 Or maybe I'm on the wrong track, and my problem has nothing to do with the Functor constraint. 或者我可能在错误的轨道上,我的问题与Functor约束无关。

I've read all the Stack Overflow questions I could find regarding the "illegal polymorphic etc" error message. 我已经阅读了有关“非法多态等”错误消息的所有Stack Overflow问题。 Perhaps this is my lack of familiarity with Haskell showing, but I can't see any of those questions being applicable to my current situation. 也许这是我对Haskell缺乏熟悉的表现,但我看不出任何这些问题适用于我目前的情况。

Nor have I been able to find any documentation on what the error message means in general. 我也没能找到任何关于错误信息通常意味着什么的文档。

Lens uses rank 2 types and you have it to the left of an arrow so to use any of lenses types like this you have to make it legal to even utter something like 镜头使用等级2类型,你可以在箭头左侧使用它,所以要使用这样的任何镜头类型你必须使它合法甚至说出类似的东西

(forall a. foo) -> bar

Which you can too with 哪个你也可以

{-# LANGUAGE RankNTypes #-} -- Rank2Types is a synonym for RankNTypes

at the top of your file. 在您的文件的顶部。 Without it, it's illegal to even use a lens type synonym since they use a part of the language you must enable. 没有它,即使使用镜头类型的同义词也是违法的,因为它们使用了您必须启用的语言的一部分。

exampleFunc fails to compile because the Lens type synonym is polymorphic and occurs in the signature in what is called "negative position", that is, to the left of the -> . exampleFunc无法编译,因为Lens类型同义词是多态的,并且在签名中出现在所谓的“负位置”,即->的左侧。

You can use Lens in a type signature even without having RankNTypes on. 即使没有使用RankNTypes ,您也可以在类型签名中使用Lens This typechecks: 这个类型检查:

import Control.Lens

lensy :: Lens' (a,b) a 
lensy = _1

But this fails to typecheck: 但这没有成功:

oops :: Lens' (a,b) a -> Int
oops = const 5 

Why? 为什么? For the same reason this also fails to typecheck without RankNTypes : 出于同样的原因,如果没有RankNTypes这也无法进行类型RankNTypes

{-# LANGUAGE ExplicitForAll #-}

fails :: (forall a. a -> Int) -> Int
fails = undefined

Here the forall is in negative position, and ranges only over the a -> Int . 这里forall处于负位置,并且范围仅在a -> Int It is the implementation of fails , and not the caller of fails , the one who chooses the type of a . 这是实施 fails ,而不是调用者 fails ,谁选择的类型,一个a The caller must supply an argument function that works for all a . 调用者必须提供适用于所有a的参数函数。 This feature requires the RankNTypes extension . 此功能需要RankNTypes扩展名

When the forall ranges over the whole signature (as when Lens is defined in isolation) there's no need for RankNTypes . forall范围超过整个签名时(如LensRankNTypes定义),不需要RankNTypes This typechecks: 这个类型检查:

{-# LANGUAGE ExplicitForAll #-}

typechecks :: forall a. (a -> Int) -> Int
typechecks = undefined

But this function is different from the previous one, because here it is the caller who chooses the type of a . 但是,这个功能是从以前的一个不同的,因为这里是谁选择的类型调用者 a He can pass an argument function which works only for a particular a . 他可以传递一个仅适用于特定a的参数函数。

exampleFunc' worked because, when no forall is specified, there are implicit foralls for each variable, ranging over the whole signature. exampleFunc'工作,因为,当没有指定forall时,每个变量都有隐式foralls ,范围在整个签名上。

This explanation from the Haskell mailing list may be useful. 来自Haskell邮件列表的这种解释可能很有用。

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

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