XTypeOperators扩展名不能用作编译指示

时间:2011-12-26 18:07:00

标签: haskell types

我正在使用GHCi 7.0.3以及实现类型级列表的以下程序:

{-# LANGUAGE TypeOperators #-}

data True
data False

-- List
data Nil
data Cons x xs

-- Type-level infix operator must begin with ':'
data x ::: xs
infixr 5 ::: -- set precedence level to 5 (tight)

它编译,但当我测试它时:

:t (undefined :: True:::Nil)

(转换为undefinedTrue:::Nil的类型是什么?)我收到此错误:

Illegal operator `:::' in type `True ::: Nil'
  Use -XTypeOperators to allow operators in types

事实上,当我用旗帜

启动GHCi时
-XTypeOperators

我得到了预期的结果:

(undefined :: True ::: Nil) :: True ::: Nil

我的问题是:为什么等效的pragma不起作用:

{-# LANGUAGE TypeOperators #-}

编辑:如果pragma没有延伸到GHCi环境,那么我还有另一个难题。我试过这个程序:

class And b1 b2 b | b1 b2 -> b where
    andf :: b1 -> b2 -> b

-- truth table
instance And True True True where andf = undefined
instance And True False False where andf = undefined
instance And False True False where andf = undefined
instance And False False False where andf = undefined

需要以下编曲:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}

但是一旦编译完毕,我就可以在GHCi中使用它了:

*Main> :t andf (undefined::True) (undefined::False)
          andf (undefined::True) (undefined::False) :: False

我想在列表的情况下,解释器甚至无法用类型级操作符:::解析表达式,而在多参数类的情况下,命令行是可解析的。但是,想想看,GHCi使用多参数类和函数依赖进行类型推断,不是吗?这种类型推断是在GHCi中完成的,而不是通过调用编译代码中的某个函数来完成的,对吗?

3 个答案:

答案 0 :(得分:14)

关于在GHCi中启用扩展的其他答案是正确的,无论是从GHCi提示还是在启动GHCi时作为标志。但是,还有第三个选项 - 您可以创建一个.ghci文件,每次启动GHCi时都会加载并运行该文件,并使用它自动启用扩展。特别是像TypeOperators这样的东西,启用它的危害很小,非常方便。

例如,这就是我现在的样子:

:set prompt "∀x. x ⊢ "
:set -XTypeOperators
import Control.Monad
import Control.Applicative
import Control.Arrow

.ghci文件会出现在系统标准位置的任何文件中。


回答你的扩展问题:有问题的代码在GHCi中工作大致是因为如果在另一个模块中使用它也可以工作,该模块使用pragma导入模块但是没有自己启用它们。 GHC能够在每个模块的基础上实现扩展,即使在没有扩展的情况下导出的定义可能没有意义,或者推断出需要它的类型。

GHCi中的区别有点模糊,因为它还将非导出的定义放在范围内的模块中,但一般来说,如果从另一个模块使用的话,任何可行的东西也可以在GHCi提示符下工作。

答案 1 :(得分:7)

你的pragma是正确的;问题是你试图在GHCi中使用它,GHCi没有继承加载模块的扩展, 1 传递给它的选项GHC编译你列出的文件(这就是为什么它与pragma具有相同的效果)。

你应该保留编译指示,并在启动GHCi时通过-XTypeOperators,或者在加载文件后启用它,如下所示:

GHCi> :set -XTypeOperators

1 这可能是非常不受欢迎的,并且在许多情况下可能是不可能的,例如加载已编译的模块。

答案 2 :(得分:4)

LANGUAGE pragma适用于源文件,它不会传播到ghci - 提示符。由于项目的多个源文件中可能存在冲突的编译指示,因此源编译指示默认不能传播到ghci - 提示符。有可能让*module的pragma在提示符下有效,我不确定,但我认为实现它是有道理的,无论如何,到目前为止,它还没有实现,所以你需要设置ghci明确的扩展名。