2016-10-17 4 views
1

왜 Haskell 인터프리터 (GHCI 7.10.3)는 let 표현식에 함수 정의가 필요하지만 Haskell 컴파일러 (GHC 7.10.3)는 파서 오류를 발생시킵니다. 함수 정의가 let 표현식 안에 있습니까?컴파일 된 대 해석 : Letter/Not To Let

"Learn You a Haskell for Great Good!" 아기의 첫 번째 기능은 doubleMe입니다 : doubleMe x = x + x

왜 let이 표현식 안에 있으면 인터프리터가이 정의를 허용하고 '='입력에 구문 분석 오류가 발생합니까? 한편, 같은 함수를 파일에서 컴파일하는 경우, 함수 정의가 let 표현식 내에 있고 let 표현식 내에 있지 않으면 정의를 컴파일하면 GHC가 구문 분석 오류를 발생시키는 이유는 무엇입니까? Lisp 배경에서 왔을 때, 나는 대화식 Haskell과 파일 로딩 및 컴파일 Haskell이 이러한 정의를 다르게 취급한다는 것에 놀랐다.

+2

규칙이 있습니다. GHCi가 .hs 파일에 쓰는 것과 똑같이 작동한다면'1 + 1'을 쓰는 것은'print (2,3)'뿐만 아니라 오류가 될 것입니다. 대신, GCHi는 약간의 마법을 사용하여 이러한 표현과 '정의'를 모두 허용했습니다. let없이'x = 1'이 거부되는 이유에 대해 - 나는 더 많은 마법이 필요하다는 것을 제외하고는 명확한 답이 없다고 생각합니다. – chi

+0

오른쪽. FWIW, [IHaskell] (https://github.com/gibiansky/IHaskell)은 두 스타일을 혼합 할 수 있습니다. – leftaroundabout

+7

GHCi (8.0.1)의 최신 버전은'doubleMe x = x + x'를 허용합니다. 당신과 같은 사람들이 이것에 대한 특별한 사례를 추가했다고 불평했습니다. :) – Alec

답변

0

현대 Lisp 구현은 프롬프트에서 코드를 입력해도 기본 코드로 컴파일되는 경우가 많습니다. Lisp의 프롬프트는 단지 명령을 입력 할 수있는 장소가 아니며 전체 언어가 Read-Evaluate-Print 루프에서 사용 가능하기 때문에 언어와 상호 작용할 수있는 곳입니다.이것은 Lisp이 텍스트를 심볼릭 식으로 읽어 들이고, 그 결과를 평가하여 모든 프린트 출력과 반환 된 값을 프린트한다는 것을 의미합니다. 예를 들어,

? (defun a-fun() nil) 
A-FUN 
? (compiled-function-p #'a-fun) 
T 
리스프, 당신은 컴파일하고 REPL에 그것을 입력하여 당신은 또한 리스프 이미지로 입력 할 수있는 파일을로드하여 리스프 이미지에 입력 할 수있는 코드와

Compiled-Function-P Clozure Common Lisp

. 그래서 GHCi 프롬프트가 REPL이기를 기대했기 때문에 놀랐습니다. @Alec은 Lisp처럼 Haskell 식으로 텍스트를 읽지 않아 평가할 수 없으므로 설명하지 않았습니다. @dfeuer에 따르면이 문제는 컴파일 대 해석에 관한 것이 아닙니다. 문제는 GHCi의 프롬프트가 Lisp의 REPL처럼 하스켈 자체와의 상호 작용보다는 하스켈 컴파일러와의 제한된 상호 작용을 제공한다는 것이다.

4

이 뒤에 이유는, (7.10.3)에 GHCi는

  • commands
  • declarations (일 같은 data, type (유형 :h에서 사용할 수있는 명령을 나열) 프롬프트에서 기대하는 것입니다 newtype, class, instance, derivingforeign하지만 하지 일반 정의)
  • 0
  • I/O Actions/do statments이 당신에게 놀라운 것 같으면

(print "hi" 또는 x <- getLine또는let doubleMe x = x + x 같은 것들), 리스프와 하스켈의 평가가 매우 떨어져 있음을 기억해 123,121,169,

  • expressions (1+1 또는 let x = 3 in x*x 같은 것들) different - Lisp은 해석되고 Haskell은 컴파일됩니다.

    알다시피, 최상위 레벨 정의는이 목록의 일부가 아닙니다. 고맙게도 이것은 GHCi 8.0.1에서 수정되었습니다. 이제는 원시 최상위 함수 선언을 지원합니다. (8.0.1)에 다음 작품 : 그것은 do 절에있는 것처럼

    ghci> doubleMe x = x + x 
    ghci> doubleMe 1 
    2 
    
  • +4

    이것은 편집 및 해석과 아무런 관련이 없습니다. 비록 실제로 Scheme이 좋은 컴파일을 위해 설계된 유일한 Lisp 일지 모르지만 실제로 많은 Lisp이 컴파일된다고 나는 믿는다. – dfeuer

    +1

    ghci의 초기 버전에서이 기능을 포함하지 않은 것에 대한 진정한 동기는 예를 들어 파일에서와 비교했을 때 ghci에서'maybeDoubleMe Nothing = Nothing \ nmaybeDoubleMe (Just x) = Just (x + x)'. –

    3

    GHCi 인터프리터 명령 줄 입력을 처리합니다. 그래서 당신은이를 입력 할 수 있습니다

    :module + System.Random 
    v <- getStdRandom $ randomR (1,10) 
    

    을 별도로 :module 지침에서이 그것이 do 절에있을 것입니다 정확히 방법이다. 즉 그것은 do 절에이 얼마나이기 때문에

    마찬가지로 당신은

    let f x = 2 * x 
    

    를 작성할 수 있습니다.