2011-01-18 6 views
2
writeStr []=putChar ' '   
writeStr (x:xs) = (putChar x)(writeStr xs) 

안녕하세요, 미리 감사드립니다, 형식 오류가 발생합니다, 그것은 간단한 대답이되어야하지만 나는 어디에서 오류가 오는지 얻지 못합니다.하스켈 작성 문자열, 쉬운 질문

+5

당신이 있습니까 쓸 수 있습니다 'putStr'과'putStrLn'을 사용하지 않는 이유는 무엇입니까? 어떤 경우에도 문자열은 문자 목록 일 뿐이므로 writeStr은 단순히 'writeStr = mapM_ putChar'로 정의 할 수 있습니다. –

답변

4

코드가 약간 이상합니다. 내가 맞으면 문자열을 인쇄하려고합니다. 당신의 방법은 첫 번째 문자열을 넣고 두 번째 문자열을 넣는 것입니다. 하지만 Haskell에서는 이와 같은 두 가지 IO 작업을 결합 할 수 없습니다. 당신이 순차적으로 여러 가지 일을하려면

writeStr []  = return() -- you had putChar ' ', 
writeStr (x:xs) = do putChar x -- but this would print a superfluous whtiespace 
        writeStr xs 

, 어느 DO-키워드 또는 모나드 콤비를 사용 : 여기가 같이 할 수 HWO이다, 이것에 대해 다시 튜토리얼 보라. 그 바로이 같은, 아주 쉬운 :

do action1 
    action2 
    action3 
    ... 
+0

감사합니다. 누락되었지만 실제로 거기에 도달 할 수 없다는 것을 알고있었습니다. 환호 – mares

+1

추신 : putchar ''도 사실 잘못되었습니다. 대신'return()'을 사용해야합니다. 이것은 빈 행동과 같습니다. 아무 것도하지 않습니다. – fuz

+0

답을 수정 하시겠습니까? –

3

FUZxxl는 즉각적인 질문에 대답했다,하지만 난 모나드에 대한 자세한 내용을 설명하기 위해 "writeStr"를 작성하는 몇 가지 더 많은 방법으로 그것을 확장하고 싶습니다. 코멘트했다 delnan으로

, 당신은 또한이 실제로 "할"표기법의 "desugared"버전입니다

writeStr [] = return() 
writeStr (x:xs) = putChar x >> writeStr xs 

쓸 수 있습니다. ">>"연산자는 모나 딕 동작을 함께 데이지 체인 방식으로 사용합니다. 실제로 ">>"연산자로 쓰여진 "bind"연산자의 특수 버전입니다. 자세한 내용은 this question을 참조하십시오.

그러나 이것을 보았을 때 우리가하는 일은 모두 인자 목록의 각 요소에 "putChar"를 적용하는 것 같습니다. 이이 일을 위해 "지도"라는 서곡의 기능은 이미, 그래서 아마 우리가 쓸 수 있습니다 : 당신이 작동하지 않습니다 때

writeStr xs = map putChar xs 

을하지만. 당신이 GHCi에 가서이를 입력하면 그 이유는 분명해진다 :

:type map putChar "Hello" 
[IO()] 

당신은 하나의 "IO()"조치를 원하지만, 이것은 당신에게 그 목록을 제공합니다. 필요한 것은이 IO 작업 목록을 단일 IO 작업으로 바꾸는 기능입니다. 다행히도 하나가 존재합니다. 전주곡은 두 번째는이처럼하지 않는 경우입니다,

sequence :: [IO a] -> IO [a] 
sequence_ :: [IO a] -> IO() 

첫 번째는 결과 목록을 할 때입니다 이러한 두 가지 기능이 포함되어 있습니다. (이 답변에 걸쳐 나는 명확성을 위해 IO-특정 유형의 서명을주는 것,하지만이 모든 기능들이 실제로 에 대한 어떤 모나드 일을 기억하는 것이 중요 해요.)

을 이제 당신이 쓸 수 있습니다 :

writeStr xs = sequence_ $ map putChar xs 

그러나이를 단축하는 방법이 있습니다. "." 연산자와 두 개의 함수를 함께 사용하는 방법과 하스켈이 함수 인자를 "currying"하는 방법은 무엇입니까? 우리는 같이 위의 기능을 다시 작성할 수 있습니다 :

writeStr = sequence_ . map putChar 

이 "점없는"스타일을보고 처음에는 매우 이상한 느낌을; "writeStr"은 함수보다 더 많이 보입니다. 그러나 코드를 읽을 때 코드 주변의 변수 이름을 추적 할 필요가 없으므로 종종 선호됩니다. 그것도 훨씬 더 짧고 더 읽을 때 "지도"또는 비슷한 높은 순서 기능에 대한 인수로 뭔가를 복잡하게하고있다.

하지만 우리는 더 짧게 갈 수 있습니다. 은 ". 순서 맵 F"패턴은 매우 일반적이기 때문에, "Control.Monad"모듈을 구현하기 위해 몇 가지 더 많은 기능을 정의

그래서
mapM :: (a -> IO b) -> [a] -> IO [b] 
mapM f = sequence . map f 

mapM_ :: (a -> IO b) -> [a] -> IO() 
mapM_ f = sequence_ . map f 

마침내

writeStr = mapM_ putChar