我正在使用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)
(转换为undefined
时True:::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中完成的,而不是通过调用编译代码中的某个函数来完成的,对吗?
答案 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
明确的扩展名。