2011-05-28 17 views
10

刚开始学习Haskell。在Haskell中调用函数 - 初学者问题

我有这里面空的源文件:

pe :: (Integral a) => a -> a 
pe y = sum [x | x <- [1..y-1], x `mod` 3 == 0 || x `mod` 5 == 0] 

现在,如果我GHCI这一点,我可以叫PE,像这样:

*Main> pe 1000 
233168 

我如何把它从我的源代码中文件?如果我有

pe 1000 

它返回一个神秘的错误:

GHC stage restriction: `pe' 
    is used in a top-level splice or annotation, 
    and must be imported, not defined locally 
In the expression: pe 1000 

我需要声明它主要还是什么?

回答

11

是的,你需要把它连接到你的main函数。例如,

main = print (pe 1000) 

如果您希望拥有多个电话,你可以用do -notation将它们结合起来:

main = do 
    print (pe 500) 
    print (pe 1000) 
+4

或'main = mapM_(print.pe)[1..1000]'如果您需要为大量的值进行操作。 – alternative 2011-05-28 00:20:18

10

一个Haskell源文件中包含的定义,而不是表达的序列。所以你不能只在文件的顶层放置一个表达式,你必须把它放在定义体内。因此,由于pe 1000不是一个定义,所以会出现错误。

但为什么这样一个神秘的错误信息呢? GHC有一个名为Template Haskell的扩展,它允许您在编译时以编程方式创建定义。为了达到这个目的,它允许你在一个通常只允许定义的地方放置一个表达式,并在编译时计算表达式,并用它的结果替换表达式(它必须是一个定义) - 这称为拼接,然后表达式就是称为拼接。这样的剪接需要满足两个要求:

  1. 在表达式中使用的任何标识符必须在不同的源文件中定义(这是必需的,以便在遇到表达式时所使用的功能已经编译的,因此可以是在编译期间调用)
  2. 表达式的类型必须是表示有效定义的模板Haskell类型。

因此,由于您的表达式pe 1000出现在只允许定义的地方,因此GHC认为它是拼接。然而,由于它不符合上述第一条标准,即它在当前文件中被定义而不是不同的文件,GHC抱怨这一点。当然,它也不符合第二个条件,但是当它产生错误信息时,GHC还没有做到这一点。如果pe在不同的源文件中定义,您会收到一条错误消息,抱怨pe的类型错误。

+0

谢谢;非常感激。 – 2011-05-28 23:07:15