GHCi의 여러 줄 명령


135

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을 사용하고 있습니다.


답변:


184

대부분의 경우 유형 유추를 사용하여 서명을 해결할 수 있습니다. 귀하의 예에서 다음이 충분합니다.

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

설명서 의 프롬프트 섹션 에있는 대화식 평가에서 ghci와의 상호 작용에 대한 자세한 내용을 확인할 수 있습니다 .


1
두 솔루션 모두 대단히 감사합니다. 그러나 나는 또 다른 관련 질문이 있습니다 : 왜 두 번째 줄에 4 개의 선행 공백이 필요합니까 (addTwo 이전)? 공백이 적거나 많으면 오류가 있습니다.
R71

9
@Rog let는 블록을 시작합니다. 블록의 항목은 들여 쓰기로 그룹화됩니다. 블록의 첫 번째 비 공백 문자는 그룹화되는 들여 쓰기를 설정합니다. let위 의 블록 에서 첫 번째 공백이 아닌 문자는의 문자이므로 블록 aaddTwo모든 행은 정확히 그만큼 깊게 들여 쓰기해야합니다 a.
Daniel Wagner

감사. 또한 다른 let / where 블록에서도 나타났습니다. 이것은 공백이 무시되는 다른 언어와 큰 차이가 있으므로 파악하기가 다소 어려웠습니다.
R71

125

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블록으로 묶어야 하스켈이 정의하려는 내용을 알 수 있습니다. :set +m물건을 여러 줄에 대한 속기 :{ 코드를 :} 구축합니다.

공백은 블록 단위로도 중요하므로 형식 정의 다음에 4 개의 공백을 설명하기 위해 함수 정의를 4 개의 공백으로 들여 써야합니다 let.


5
간단하지만 명확하지는 않습니다. 나는 1 페이지에 나에게 그것을 말하지 않기 위해 사용했던 책에서 비명을 지르고 싶었다!
Tim

2
Linux 셸 echo ':set +m' >> ~/.ghci에서이 설정을 유지합니다.
truthadjustr

let첫 번째 줄에 그 자체를 가질 수 있으며 나머지는 전혀 들여 쓰기 할 필요가 없습니다. 공백이 실제로 중요한 곳은 줄에 후행 공백이 없어야합니다. 후행 공백은 추가 Enter로 계산되고 여러 줄 블록을 끊습니다.
Will Ness

14

사용 let:

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

5

현재 GHCI 버전 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

2

버전 GHCi 8.4.4에서는 Aaron Hall의 답변 을 확장 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

하지만 :{, :}기술은 않습니다.


1
실제로, 심지어 이전에도을 입력 :{하고 다음 줄 let에 그다음에 들여 쓰기를 추가하지 않고 정의를 붙여 넣은 다음로 닫을 수 있습니다 :}. :) 및 다중 라인 입력 모드 세트 ( :set +m)를 사용하면 코드 라인에 후행 공백이 없으면 중괄호 명령이 필요하지 않습니다.
Will Ness

아, 그래서 :set +m당신은 let자신의 라인에서 사용할 수 있습니까? 그래서 당신은 할 수 있습니다-멋지다. 감사합니다.
davidA

흠, 단순히 입력 let한 다음 줄 바꿈이 작동하지 않는 경우를 발견 했습니다. 내 편집을 참조하십시오.
davidA
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.