首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Control.Lens中的“非法多态或合格类型”

Control.Lens中的“非法多态或合格类型”
EN

Stack Overflow用户
提问于 2013-11-20 19:28:57
回答 2查看 1.8K关注 0票数 11

我和Control.Lens一起工作。我正在编写的实际函数相当复杂,但就这个问题而言,我将其归结为一个最小的失败示例:

代码语言:javascript
复制
import Control.Lens    

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

这无法编译,产生以下错误消息:

代码语言:javascript
复制
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

为什么这是非法的?它似乎与确实编译的以下内容非常相似:

代码语言:javascript
复制
import Data.Maybe

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

因此,我假设区别在于Lens的定义。但是,Lens类型如何使exampleFunc的类型成为非法呢?我隐约怀疑它与Lens定义中的Functor资格有关,但我可能错了。值得借鉴的是,定义 of Lens是:

代码语言:javascript
复制
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t

那么,我是否必须在某种程度上满足FunctorexampleFunc定义中的限定?如果是这样的话,是怎么做的?我看不出在我的类型签名中我有机会声明这个约束。或者我走错了轨道,我的问题与Functor约束无关。

我已经阅读了关于“非法多态等”错误消息的所有堆栈溢出问题。也许这是因为我对Haskell缺乏了解,但我看不出其中任何一个问题都适用于我目前的情况。

我也没有找到任何关于错误信息的一般含义的文档。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-20 19:43:42

镜头使用等级2的类型,而你把它放在箭头的左边,所以要使用像这样的任何透镜类型,你必须使它成为合法的,甚至说出类似的东西。

代码语言:javascript
复制
(forall a. foo) -> bar

你也可以用它

代码语言:javascript
复制
{-# LANGUAGE RankNTypes #-} -- Rank2Types is a synonym for RankNTypes

在你档案的顶端。没有它,即使使用透镜类型的同义词也是违法的,因为它们使用的是你必须启用的语言的一部分。

票数 9
EN

Stack Overflow用户

发布于 2013-11-20 21:48:54

exampleFunc无法编译,因为Lens类型的同义词是多态的,并且在签名中出现在所谓的“否定位置”,即->的左边。

即使不打开Lens,也可以在类型签名中使用RankNTypes。这种打字机:

代码语言:javascript
复制
import Control.Lens

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

但这并不能说明问题:

代码语言:javascript
复制
oops :: Lens' (a,b) a -> Int
oops = const 5 

为什么?出于同样的原因,这也不能在没有RankNTypes的情况下进行排版。

代码语言:javascript
复制
{-# LANGUAGE ExplicitForAll #-}

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

在这里,forall处于负位置,并且范围仅在a -> Int上。它是fails的实现,而不是选择a类型的fails的调用者。调用方必须提供一个适用于所有a的参数函数。这个特性需要RankNTypes扩展

forall覆盖整个签名(比如Lens是孤立定义的)时,就不需要RankNTypes了。这种打字机:

代码语言:javascript
复制
{-# LANGUAGE ExplicitForAll #-}

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

但是这个函数不同于前一个函数,因为这里是调用者选择了a的类型。他可以传递一个仅适用于特定a的参数函数。

exampleFunc'之所以有效,是因为当没有指定forall时,每个变量都有隐式foralls,其范围涵盖整个签名。

来自Haskell邮件列表的这一解释可能是有用的。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20105147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档