首页 > 解决方案 > 什么干扰了我的作用域类型变量?

问题描述

过去几天我一直害怕问这个问题,因为它的特点是我没有注意到一个小错误,所以如果是这种情况,我真诚地道歉。

我正在尝试编写自己的scanr作为我正在编写的库的一部分。代码如下所示:

-- Language Extensions for the file --
{-# Language BangPatterns #-}
{-# Language FlexibleInstances #-}
{-# Language FlexibleContexts #-}
{-# Language QuantifiedConstraints #-}
{-# Language UndecidableInstances #-}
{-# Language ScopedTypeVariables #-}

rightScan ::
  ( Foldable f
  )
    => forall a b . (a -> b -> b) -> b -> f a -> NonEmpty [] b
rightScan g start as = start :| reverse (rightFold addOn [] as)
  where
    addOn :: a -> [b] -> [b]
    addOn new (c : cs) = g new c : c : cs
    addOn new [] = [g new start]

(myNonEmpty实际上是由一个容器参数化的(本例中[]),myNonEmpty []相当于传统的NonEmpty。)

现在这有两个错误:

• Couldn't match expected type ‘a’ with actual type ‘a1’
  ‘a1’ is a rigid type variable bound by
    the type signature for:
      addOn :: forall a1 b1. a1 -> [b1] -> [b1]

和非常相似的

• Couldn't match expected type ‘b’ with actual type ‘b1’
  ‘b1’ is a rigid type variable bound by
    the type signature for:
      addOn :: forall a1 b1. a1 -> [b1] -> [b1]

现在这些错误很容易理解。它认为ain的签名与inrightScran的签名不同,而与 的签名相同。但是,我已经对类型变量进行了限定,并且这两个变量都是在父级中引入的。aaddOnbforall

现在我可以删除签名addOn来解决问题,但我完全困惑为什么作用域类型变量在这里不起作用。

所以问题是:我在这里的作用域类型变量做错了什么?

标签: haskellscoped-type-variables

解决方案


问题在于forall. 它需要出现在约束之前并列出所有类型变量,包括f. forall f a b. (Foldable f) => ....

按照您编写的方式,forall 的作用域并不涵盖整个类型,因此它绑定的类型变量被认为是该类型的本地变量。这是由 启用的RankNTypes,它包含在QuantifiedConstraints.


推荐阅读