GHCi中的多行命令

时间:2011-12-09 08:45:33

标签: haskell ghci

我在输入ghci中的多行命令时遇到问题。

以下2行代码适用于文件:

addTwo :: Int -> Int -> Int
addTwo x y = x + y

但是当我进入ghci时,我收到一个错误:

<interactive>:1:1: error:
    Variable not in scope: addTwo :: Int -> Int -> Int

我也尝试将代码放在:{ ... :}中,但它们也不适用于此示例,因为这只是将行附加到一行,这不应该是这种情况。

我正在使用WinGHCi,版本2011.2.0.1

5 个答案:

答案 0 :(得分:157)

大多数情况下,您可以依靠类型推断来为您制作签名。在您的示例中,以下内容就足够了:

Prelude> let addTwo x y = x + y

如果你真的想要一个带有类型签名的定义,或者你的定义跨越多行,你可以在ghci中这样做:

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y 
Prelude| :}
Prelude> addTwo 4 7
11

请注意,您也可以将其挤压到一行:

Prelude> let addTwo :: Int -> Int -> Int ; addTwo x y = x + y

您可以在文档的Interactive evaluation at the prompt部分找到有关与ghci交互的更多信息。

答案 1 :(得分:100)

通过启动GHCI并输入:set +m来解决此问题:

Prelude> :set +m
Prelude> let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| 
Prelude> addTwo 1 3
4

动臂。


这里发生了什么(我主要是在谈论,在搜索Learn You A Haskell的过程中搜索帮助的人)是GHCI是一个互动的环境,你在这里动态更改函数名称的绑定。您必须将函数定义包装在let块中,以便Haskell知道您将要定义某些内容。 :set +m内容是多行:{ 代码 :}构造的简写。

空格在块中也很重要,因此您必须在类型定义后用四个空格缩进函数定义以考虑let中的四个空格。

答案 2 :(得分:13)

使用let

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| :}
Prelude> addTwo 2 3
5

答案 3 :(得分:2)

GHCI version 8.0.1开始,不再需要let来定义REPL上的功能。

所以这对您应该很好:

λ: addTwo x y = x + y
λ: addTwo 1 2
3
λ: :t addTwo
addTwo :: Num a => a -> a -> a

Haskell的类型推断提供了适用于浮点数的通用类型:

λ: addTwo 2.0 1.0
3.0

如果您必须提供自己的键入内容,则似乎需要结合使用let和多行输入(使用:set +m来启用GHCI中的多行输入):

λ: let addTwo :: Int -> Int -> Int
 |     addTwo x y = x + y
 | 
λ: addTwo 1 2
3

但是如果您尝试传递Int以外的任何内容,则由于非多态输入,您会遇到错误:

λ: addTwo 2.0 1.0

<interactive>:34:8: error:
    • No instance for (Fractional Int) arising from the literal ‘2.0’
    • In the first argument of ‘addTwo’, namely ‘2.0’
      In the expression: addTwo 2.0 1.0
      In an equation for ‘it’: it = addTwo 2.0 1.0

答案 4 :(得分:2)

要至少在GHCi 8.4.4版的Aaron Hall's answer上进行扩展,如果您使用let :{,则无需在类型声明中使用:}风格。这意味着您不必担心在每个后续行上添加4个空格的缩进,以解决let的问题,使更长的函数更易于键入,或者在许多情况下,易于复制粘贴(因为原始来源可能没有正确的缩进):

λ: :{
 | addTwo :: Int -> Int -> Int
 | addTwo x y = x + y
 | :}
λ: addTwo 1 2
3

更新

作为替代方案,您可以使用:set +m打开多行输入模式,然后单独键入let,按Enter,然后粘贴不需要缩进的定义。

但是,这似乎不适用于某些代码块,例如:

class Box a where
  mkBox :: a -> Boxes.Box

但是:{:}技术确实有用。