2016-09-11 2 views
0

하스켈 프로그래밍의 첫 번째 원칙 책에는 공백이있는 문자열을 입력하고 공백으로 분할 한 다음 비 공백 청크를 문자열 목록에로드하는 함수를 작성하는 방법이 나와 있습니다. 내 첫 번째 시도했다 :

splitString :: String -> [String] 
splitString str 
    | str == "" = [] 
    | otherwise = takeWhile (/=' ') str : splitString $ drop 1 $ dropWhile (/=' ') str 

지금이 컴파일되지 않습니다. 내가 대신과 같이 괄호의 대응 쌍의 첫 번째 ($) (오른쪽 splitString 후)를 교체하는 경우 :

takeWhile (/=' ') str : splitString (drop 1 $ dropWhile (/=' ') str) 

을 다음 작동합니다. 지금까지 배운 내용을 바탕으로, 두 가지가 동등하지 않아야합니까? ($)는 바로 연관, 그래서이 일이되어야한다 무엇처럼 나에게 보이는

  1. dropWhile (/=' ') str
  2. drop 1 (dropWhile (/=' ') str)
  3. 다음, 결과는 splitString에 전달되는 것입니다 먼저 평가이다. 대신

, 나는

Couldn't match expected type ‘[Char] -> [String]’ 
      with actual type ‘[[Char]]’ 
The first argument of ($) takes one argument, 
but its type ‘[[Char]]’ has none 

은 내가 볼 수 있다고 ghc에서 오류가 발생하는 것을 "($)의 첫 번째 인수"하여 약 splitString을 얘기,하지만 난 어떤 진술에 의해 의아해 해요

but its type `[[Char]]` has none 

을 의미합니다.

+0

당신이 바로, 'words'을 구현 알고 있습니까? – chepner

+0

@chepner : no ... 나는 그것을 몰랐다. 저는 하스켈에게 총 초보자입니다. 나는 그것이 어떻게 작동하는지 알고 싶다. – gogurt

+0

왜 downvote?누구나 항상'$ '연산자를 괄호로 묶는 것과 같은 것으로 설명하지만,이 경우에는 분명하지 않습니다. 그리고 그 이유를 이해하는 것이 중요하다고 느꼈습니다. – gogurt

답변

8

당신이 괄호를 추가하면 아래에 표시된대로 귀하의 코드가 작동합니다 : 당신이 언급

(takeWhile (/=' ') str : splitString) 
    $ drop 1 
    $ dropWhile (/= ' ') str 

업데이트

버전 :

... 
    | otherwise = takeWhile (/=' ') str : (splitString $ drop 1 $ dropWhile (/=' ') str) 
--          ^^^           ^^^                       

그렇지 않으면 하스켈로, 그렇지 않으면 절을 해석한다 의견에 :

 takeWhile (/= ' ') str : splitString (...) 
-- \__ a __/ \_ b _/ c : \___ d ___/ \_ e _/ 

의 형식은 a b c : d e이며, 하스켈은 :이 표현식을 나타내는 유일한 중위 연산자이기 때문에 항상 (a b c) : (d e)으로 해석합니다.

a b c : d e $ f $ g 

당신이 고려 사항으로 :$ 중위 사업자의 상대적 우선해야 : 당신이 뭔가를 가지고

. $defined as infixr 0이기 때문에, :로 꽉 바인드하지 않습니다 그리고 당신은 다음 마우스 오른쪽 연관 그룹화 수 :

(a b c : d e) $ (f $ g) 
+0

하지만 그 이유는 무엇입니까? 내 질문에 제안한 것처럼 괄호를 추가하면 하스켈은 여전히 ​​그룹화하려고 시도해서는 안됩니다. 왼쪽에있는 블록에 'splitString'을 쓰는 이유는 무엇입니까? 다른 하나는 그렇지 않습니다. – gogurt

+0

@gogurt'(:)'연산자는 우선 순위가 5이지만'($)'는 우선 순위가 0이므로'(:)'는'($)'보다 더 엄격하게 바인딩됩니다. –

+0

오른쪽. 하지만 나는'takeWhile (/ = '') str : splitString (drop 1 $ dropWhile (/ = ''str)')이라는 버전에 대해 묻고 있었다. 이것은 ErikR의 대답처럼 'splitString'을 명시 적으로':'의 오른쪽에 그룹화하지 않았지만 어떤 이유로 작동합니다. – gogurt

관련 문제