Multi-line commands in GHCi

前提是你 提交于 2019-11-26 05:57:38

问题


I am having problem in entering multi-line commands in ghci.

The following 2-line code works from a file:

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

But when I enter in ghci, I get an error:

<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


回答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:

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.




回答2:


Solve this problem by firing up GHCI and typing :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. You have to wrap your function definitions in a let block, so that Haskell knows that you're about to define something. The :set +m stuff is shorthand for the multiline :{ code :} construct.

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.




回答3:


Use let:

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



回答4:


As of GHCI version 8.0.1, let is no longer required to define functions on the 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:

λ: 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 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:

λ: 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


来源:https://stackoverflow.com/questions/8443035/multi-line-commands-in-ghci

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!