我正在使用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)
Run Code Online (Sandbox Code Playgroud)
它编译,但当我测试它:
:t (undefined :: True:::Nil)
Run Code Online (Sandbox Code Playgroud)
(什么是转换为类型undefined时的类型True:::Nil?)我收到此错误:
Illegal operator `:::' in type `True ::: Nil'
Use -XTypeOperators to allow operators in types
Run Code Online (Sandbox Code Playgroud)
事实上,当我用旗帜开始GHCi时
-XTypeOperators
Run Code Online (Sandbox Code Playgroud)
我得到了预期的结果:
(undefined :: True ::: Nil) :: True ::: Nil
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么等效的pragma不起作用:
{-# LANGUAGE TypeOperators #-}
Run Code Online (Sandbox Code Playgroud)
编辑:如果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
Run Code Online (Sandbox Code Playgroud)
它需要以下pragma:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
Run Code Online (Sandbox Code Playgroud)
但是一旦编译完毕,我就可以在GHCi中使用它了:
*Main> :t andf (undefined::True) (undefined::False)
andf (undefined::True) (undefined::False) :: False
Run Code Online (Sandbox Code Playgroud)
我想在列表中的情况下解释甚至无法解析与类型级运营商的表达:::,而在多参数类的情况下,命令行是可分析的.但是,想想看,GHCi使用多参数类和函数依赖进行类型推断,不是吗?这种类型推断是在GHCi中完成的,而不是通过调用编译代码中的某些函数来做对的,对吗?
C. *_*ann 14
关于在GHCi中启用扩展的其他答案是正确的,无论是从GHCi提示还是在启动GHCi时作为标志.但是,还有第三个选项 - 您可以创建一个.ghci文件,每次启动GHCi时都会加载并运行该文件,并使用它自动启用扩展.特别是对于这样的事情TypeOperators,启用它的危害非常小,它非常方便.
例如,这就是我现在的样子:
:set prompt "?x. x ? "
:set -XTypeOperators
import Control.Monad
import Control.Applicative
import Control.Arrow
Run Code Online (Sandbox Code Playgroud)
.ghci无论系统的标准位置是什么,该文件都会进入此类文件.
回答你的扩展问题:有问题的代码在GHCi中工作大致是因为如果在另一个模块中使用它也可以工作,该模块使用pragma导入模块但是没有自己启用它们.GHC能够在每个模块的基础上实现扩展,即使导出的定义在没有扩展的情况下可能没有意义,或者推断出需要它的类型.
GHCi中的区别有点模糊,因为它还将非导出的定义放在范围内的模块中,但一般来说,如果从另一个模块使用的话,任何可行的东西也可以在GHCi提示符下工作.
你的pragma是正确的; 问题是你试图在GHCi中使用它,它不继承加载模块的扩展,1但确实传递给GHC的选项来编译你列出的文件(这就是为什么它有与pragma相同的效果).
你应该保留pragma,并-XTypeOperators在启动GHCi时通过,或者在加载文件后启用它,如下所示:
GHCi> :set -XTypeOperators
Run Code Online (Sandbox Code Playgroud)
1对于例如加载编译模块,这可能是非常不合需要的,并且在许多情况下可能是不可能的.