繁体   English   中英

为什么 GHC 拒绝允许这种存在类型函数?

[英]Why does GHC refuse to allow this existential type function?

我已经定义了一个通用的heterogenous ,我称之为(我不知道这是否正确),输入:

data Heterotype f = forall a. f a => Heterotype a

然后我决定创建一个函数,允许您从多态值创建异型:

hset :: (forall a. f a => a) -> Heterotype f
hset x = Heterotype x

但是,GHC 抱怨以下内容:

████████.hs:15:10: error:
    * Could not deduce: f a0 arising from a use of `Heterotype'
    * In the expression: Heterotype x
      In an equation for `hset': hset x = Heterotype x
    * Relevant bindings include
        x :: forall a. f a => a
          (bound at ████████.hs:15:6)
        hset :: (forall a. f a => a) -> Heterotype f
          (bound at ████████.hs:15:1)
   |
15 | hset x = Heterotype x
   |          ^^^^^^^^^^^^

编辑:启用以下扩展:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
{-# LANGUAGE NoStarIsType, ConstraintKinds #-}
{-# LANGUAGE AllowAmbiguousTypes, RankNTypes #-}
import Data.Kind

从逻辑的角度来看,您的代码将对应于逻辑公式的证明,可以如下(粗略地)阅读:

  • f是任何类型的属性;
  • 假设,对于满足f任何类型a ,我们可以产生类型a的值x
  • 那么,存在满足f且值为x的类型a

这在逻辑上是不合理的。 事实上,无论a是什么, fa都可能永远不成立。 在这种情况下,上面的假设空洞地成立,因此它是正确的。 然而,上述结论与fa总是错误的事实相矛盾。

因此,我们无法使用该类型定义您的hset

为了使论证合理,我们必须添加一个额外的假设,即存在某种类型b使属性f真。 如果我们加上这个假设,我们可以证明这个陈述:

-- (untested, but should work)
hset :: forall b . f b => (forall a. f a => a) -> Heterotype f
hset x = Heterotype (x :: b)

您的数据定义隐藏的monotyped选择a被包装起来,从词典的价值f 重要的是要认识到,这样做的全部意义在于丢弃有关特定类型的信息,同时保留与该类型关联的实例字典。

这与您在hset尝试执行的操作不hset 从来没有一个具体的类型来打包实例。 这些部分不能以这种方式组合在一起,因为它们都缺少相同的必需的东西。 Heterotype f(forall a. fa => a)都缺乏一个具体的类型来选择一个实例,但是Heterotype构造器需要一个具体的实例来包含。 只是信息不存在。 这些部分是不兼容的。

您有点过度指定了:),以下工作正常:

data Heterotype f = forall a. f a => Heterotype a

hset :: forall f a. f a => a -> Heterotype f
hset x = Heterotype x

不同之处在于您已经量化了您的参数: (forall a. fa => a)表示此函数接受一个表达式,该表达式必须同时是任何可能的类型(调用者不能选择特定的“a”) ,这真的没有意义。 新版本(因此是相同的只是用Heterotype自身的构造函数)说,来电者被允许挑选的类型a ,它可以是任何东西,但必须只有一个类型(一次有效)。

习惯存在主义可能需要一些练习; 最好的方法是反复试验:)

暂无
暂无

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

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