在Haskell中调用函数 - 初学者问题

Dom*_*mra 10 haskell

刚开始学习Haskell.

我有一个空的源文件,里面有这个:

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

现在,如果我这样做,我可以像这样打电话给pe:

*Main> pe 1000
233168
Run Code Online (Sandbox Code Playgroud)

如何在源文件中调用它?如果我有

pe 1000
Run Code Online (Sandbox Code Playgroud)

它返回一个神秘的错误:

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
Run Code Online (Sandbox Code Playgroud)

我需要在主要内容声明它吗?

ham*_*mar 11

是的,你需要把它连接到你的main功能.例如,

main = print (pe 1000)
Run Code Online (Sandbox Code Playgroud)

如果要进行多次调用,可以将它们与do-notation 结合使用:

main = do
    print (pe 500)
    print (pe 1000)
Run Code Online (Sandbox Code Playgroud)

  • 或者`main = mapM_(print.pe)[1..1000]`如果你需要为大量的值做这件事. (4认同)

sep*_*p2k 10

Haskell源文件包含一系列定义,而不是表达式.因此,您不能只将表达式放在文件的顶层,您必须将它放在定义的主体内.因此,既然pe 1000不是定义,就会出错.

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

  1. 表达式中使用的任何标识符都必须在不同的源文件中定义(这是必需的,以便在遇到表达式时已经编译了已使用的函数,因此可以在编译时调用它们)
  2. 表达式的类型必须是Template Haskell类型,它表示有效的定义.

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