繁体   English   中英

嵌套函数定义中的 Haskell 范围使用 where

[英]Haskell scoping in nested function definitions using where

我对 Haskell 在where定义中的范围界定有问题。 当我有以下函数f ,我想将x传递给本地定义的函数f1而不明确使用它作为参数时,我收到一条错误消息,指出x的类型与f1的输出中的类型不兼容,虽然应该是一样的:

f :: Eq a => a -> [a]
f x = f1 x
    where
        f1 :: Eq a => a -> [a]
        f1 y = [ x, y ]

错误如下:

Couldn't match expected type `a1' against inferred type `a'
      `a1' is a rigid type variable bound by
           the type signature for `f1' at test.hs:4:11
      `a' is a rigid type variable bound by
          the type signature for `f' at test.hs:1:8
    In the expression: x
    In the expression: [x, y]
    In the definition of `f1': f1 y = [x, y]
Failed, modules loaded: none.

但是,当我将x作为附加参数传递时,正如我在以下代码中使用函数g所做的那样,它工作正常:

g :: Eq a => a -> [a]
g x = g1 x x
    where
        g1 :: Eq a => a -> a -> [a]
        g1 x y = [ x, y ]

有没有一种方法,使式af的类型兼容a (或a1 )在f1

戴夫就在上面。 另一种思考方式是,即使您的两个类型签名都引用了变量a ,但它实际上并不是相同的类型变量。 在 Haskell-prime 符号中,两个签名都可以更明确地写为:

forall a . Eq a => a -> [a]

这意味着对于这两个函数,它们都可以接受任何类型的参数(在 Eq 内)。 这显然不是这里的情况。 在标准 Haskell 98 中,唯一的选择是放弃f1的类型签名。 但是 GHC(和其他人?)支持词法范围的类型变量 所以你可以写

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a. Eq a => a -> [a]
f x = f1 x
    where
        f1 :: a -> [a]
        f1 y = [ x, y ]

那会很好用。

您的代码的问题是本地范围的 f1 类型签名。 它指定 f1 可以采用任何类型

f1 :: Eq a => a -> [a]

尽管这是一个本地函数,但您已经将这个函数概括为能够采用 f 中不存在的类型,无论该函数接收到的任何内容都必须来自 f,因此类型签名是不必要的。

只需删除 f1 类型签名。

编辑:把我的帖子读回自己,有点不清楚。 f1 中的 a 是一个可以接受任何东西的参数化类型,但是传递给它的参数已经在 f 中绑定了。 所以这个函数只能接收它的父函数接收的东西,你给它的类型签名打破了这个规则。 希望这更清楚一点。

暂无
暂无

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

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