여러 줄에서 ghci로 함수를 정의하는 방법은 무엇입니까?


161

여러 줄에 걸쳐있는 간단한 함수를 ghci로 정의하려고합니다. 다음을 예로 들어 보겠습니다.

let abs n | n >= 0 = n
          | otherwise = -n

지금까지 첫 번째 줄 다음에 Enter 키를 눌러 보았습니다.

Prelude> let abs n | n >= 0 = n
Prelude>           | otherwise = -n
<interactive>:1:0: parse error on input `|'

또한 :{and :}명령 을 사용하려고 시도했지만 멀리 가지 않았습니다.

Prelude> :{
unknown command ':{'
use :? for help.

Linux에서 Haskell 98 용 GHC Interactive 버전 6.6을 사용하고 있습니다. 무엇을 놓치고 있습니까?


20
GHC 설치를 업그레이드하십시오. GHC 6.6은 거의 5 살입니다! Haskell의 최신 버전은 다음과 같습니다. haskell.org/platform
Don Stewart

의 중복 가능성 GHCi에서 멀티 라인 명령
MMMMMM

1
@Mark이 OP는 이미 해당 문제에 대한 솔루션을 시도했습니다. 이 문제는 오래된 ghci로 인해 수행 할 작업에 대한 지식이 부족합니다. 해결 방법 : 업그레이드. 이 솔루션 : 사용 :{, :}.
AndrewC

답변:


124

경비원 (예 : 귀하의 예)의 경우 한 줄에 모두 배치 할 수 있으며 작동합니다 (경비는 간격에 신경 쓰지 않습니다)

let abs n | n >= 0 = n | otherwise = -n

인수와 패턴이 일치하는 여러 정의로 함수를 작성하려면 다음과 같이하십시오.

fact 0 = 1
fact n = n * fact (n-1)

그런 다음 세미콜론과 함께 중괄호를 사용하여 정의를 구분합니다.

let { fact 0 = 1 ; fact n = n * fact (n-1) }

258

GHCi는 이제 : set + m으로 활성화 된 다중 라인 입력 모드를 갖습니다. 예를 들어

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800

39
멀티 라인 모드를 설정 ghci하면 이와 관련하여 Python 인터프리터와 매우 유사 하게 작동합니다. 매우 편리합니다! 실제로 .ghci홈 디렉토리에 파일을 만들 수 있으며 :set +m시작할 때마다 여러 줄 모드가 기본값이됩니다 ghci!
kqr

2
정말 대단합니다. 그러나 나는 :set prompt "λ "계속 줄을 사용 하여 프롬프트를 설정하면 Prelude대신 대신 라고 말합니다 λ. 이 문제를 해결할 방법이 있습니까?
abhillman

2
새로운 연속 프롬프트를 정의하는 패치는 여기를 참조하십시오. ghc.haskell.org/trac/ghc/ticket/7509#no1
karakfa

4
연속 줄에 Prelude가 나타나지 않도록하려면 .ghci에 : set prompt2 "|"를 추가하십시오.
Nick

12
후행을 사용하여 들여 쓰기를 완전히 피할 수 있습니다 let. 간단히 a let다음에 줄 바꿈을 입력하십시오 : let⏎. 그런 다음 fac 0 = 1⏎. 그런 다음 fac n = n * fac (n-1)⏎ ⏎하면 모든 작업이 완료됩니다!
Iceland_jack

62

댄은 정확하지만 :{:}각 자신의 행에 표시해야합니다

> :{ 
> let foo a b = a +
>           b
> :}
> :t foo
foo :: (Num a) => a -> a -> a

이것은 또한 레이아웃 규칙과 상호 작용하므로 do-notation을 사용할 때 중괄호와 세미콜론을 명시 적으로 사용하는 것이 더 쉬울 수 있습니다. 예를 들어이 정의는 실패합니다.

> :{
| let prRev = do
|   inp <- getLine
|   putStrLn $ reverse inp
| :}
<interactive>:1:18:
    The last statement in a 'do' construct must be an expression

그러나 중괄호와 세미콜론이 추가되면 작동합니다.

> :{
| let prRev = do {
|   inp <- getLine;
|   putStrLn $ reverse inp;
| }
| :}
> :t prRev
prRev :: IO ()

들여 쓰기가 변경 될 수있는 파일에서 정의를 붙여 넣을 때만 중요합니다.


최소한 버전 7.6.3에서 '='로 끝나는 행 (다음 줄에 다음 정의가 있음)이있는 경우에는 작동하지 않습니다.
AdamC

1
let의 두 번째와 세 번째 줄이 충분히 들여 쓰기되지 않았기 때문에 이것은 아마도 실패합니다. (두 개의 공간이 더 있습니다.)
Evi1M4chine


7

:{and 로만 GHC를 업그레이드하지 않으려면 :}한 줄에 모두 작성해야합니다.

> let abs' n | n >= 0 = n | otherwise = -n

Haskell 에서 여러 줄로 작성 해야하는 단일 정의에 대해 잘 모릅니다 . 위의 내용은 실제로 GHCi에서 작동합니다.

> :t abs'
abs' :: (Num a, Ord a) => a -> a

do블록 과 같은 다른 표현식의 경우 중괄호와 세미콜론 (eugh)과 함께 비 레이아웃 구문을 사용해야합니다.


0

macOS Catalina 10.15.2에서 GHCi 버전 8.2.1을 사용하고 있습니다. 다음은 함수 유형 선언과 가드를 모두 결합하는 방법입니다. 왼쪽의 세로 막대는 GHCi 여러 줄에 대한 것입니다.

λ: let abs' :: (Num a, Ord a) => a -> a
 |     abs' n | n >= 0 = n | otherwise = -n
 | 
λ: abs' 7
7
λ: abs' (-7)
7

1
사용 :{하고 타입 선언 전에 :}지정할 필요가 없다면 let , 두 번째와 그 이후의 줄을 들여 쓸 필요가 없습니다.
davidA

davidA 감사합니다. 바로 내가 찾던 것이지만 찾지 못했습니다.
Golden Thumb

0

두 줄을 한 번에 붙여 넣거나 새 줄마다 control-enter를 사용하면 적어도 https://repl.it/languages/haskell 에서 모두 함께 유지하는 것처럼 보입니다 . 두 번째 줄의 시작 부분에 2 개의 점이 표시됩니다. 또는 파일에 넣고 파일을로드하십시오 (: l main). abs가 음수와 어떻게 작동하지 않습니까? 아, 숫자를 괄호로 묶어야합니다.

   let abs n | n >= 0 = n 
..           | otherwise = -n
   abs (-1)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.