简体   繁体   English

GHCi 中的多行命令

[英]Multi-line commands in GHCi

I am having problem in entering multi-line commands in ghci.我在 ghci 中输入多行命令时遇到问题。

The following 2-line code works from a file:以下 2 行代码适用于文件:

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

But when I enter in ghci, I get an error:但是当我输入ghci时,出现错误:

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

I also tried putting the code inside :{ ... :} , but they are also not working for this example, because this is just appending the lines into one line, which should not be the case.我也尝试将代码放在:{ ... :} ,但它们也不适用于此示例,因为这只是将行附加到一行中,而不应该是这种情况。

I am using WinGHCi, version 2011.2.0.1我使用的是 WinGHCi,版本 2011.2.0.1

Most of the time, you can rely on type inference to work out a signature for you.大多数情况下,您可以依靠类型推断为您计算出签名。 In your example, the following is sufficient:在您的示例中,以下内容就足够了:

Prelude> let addTwo x y = x + y

If you really want a definition with a type signature, or your definition spans over multiple lines, you can do this in ghci:如果你真的想要一个带有类型签名的定义,或者你的定义跨越多行,你可以在 ghci 中做到这一点:

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

Note that you can also squeeze this onto one line:请注意,您也可以将其压缩到一行上:

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

You can find out more about interacting with ghci on the Interactive evaluation at the prompt section of the documentation.您可以在文档的提示部分的交互式评估中找到有关与 ghci 交互的更多信息。

Solve this problem by firing up GHCI and typing :set +m :通过启动 GHCI 并输入:set +m来解决这个问题:

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

Boom.繁荣。


What's going on here (and I'm talking mostly to you , person googling for help while working your way through Learn You A Haskell ) is that GHCI is an interactive environment where you're changing bindings of function names on the fly.这是怎么回事(和我说主要是为了,人使用Google的帮助,同时通过工作的方式了解你的Haskell )是GHCI是你们在飞行中改变的函数名绑定一个互动的环境。 You have to wrap your function definitions in a let block, so that Haskell knows that you're about to define something.您必须将您的函数定义包装在一个let块中,以便 Haskell 知道您将要定义一些东西。 The :set +m stuff is shorthand for the multiline :{ code :} construct. :set +m是多行:{ code :}结构的简写。

Whitespace is also significant in blocks, so you have to indent your function definition after your type definition by four spaces to account for the four spaces in let .空格在块中也很重要,因此您必须在类型定义之后将函数定义缩进四个空格以解释let的四个空格。

Use let :使用let

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

As of GHCI version 8.0.1 , let is no longer required to define functions on the REPL.GHCI 版本 8.0.1 开始,不再需要let在 REPL 上定义函数。

So this should work fine for you:所以这应该适合你:

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

Haskell's type-inference provides generalized typing that works for floats as well: Haskell 的类型推断提供了适用于浮点数的通用类型:

λ: addTwo 2.0 1.0
3.0

If you must provide your own typing, it seems you'll need to use let combined with multiline input (use :set +m to enable multiline input in GHCI):如果您必须提供自己的输入,似乎您需要将let与多行输入结合使用(使用:set +m在 GHCI 中启用多行输入):

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

But you'll get errors if you try to pass anything but an Int because of your non-polymorphic typing:但是,如果由于您的非多态类型而尝试传递除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

To expand on Aaron Hall's answer , in version GHCi 8.4.4 at least, you don't need to use let with type declarations if you use the :{ :} style.为了扩展Aaron Hall 的答案,至少在 GHCi 8.4.4 版本中,如果您使用:{ :}样式,则不需要将let与类型声明一起使用。 This means you don't have to worry about adding the 4-space indentation on every subsequent line to account for let , making longer functions much easier to type, or in many cases, copy-paste (since the original source likely won't have the correct indentation):这意味着您不必担心在每个后续行上添加 4 个空格的缩进来说明let ,从而使更长的函数更容易键入,或者在许多情况下,复制粘贴(因为原始源可能不会有正确的缩进):

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

Update更新

As an alternative you can turn on multi-line input mode with :set +m , then type let on its own, hit Enter, then paste definitions with no indentation required.作为替代方案,您可以使用:set +m打开多行输入模式,然后单独键入let ,按 Enter,然后粘贴定义而不需要缩进。

However this doesn't seem to work with some code blocks, such as:但是,这似乎不适用于某些代码块,例如:

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

But the :{ , :} technique does.但是:{ , :}技术确实如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM