writeStr []=putChar ' '
writeStr (x:xs) = (putChar x)(writeStr xs)
안녕하세요, 미리 감사드립니다, 형식 오류가 발생합니다, 그것은 간단한 대답이되어야하지만 나는 어디에서 오류가 오는지 얻지 못합니다.하스켈 작성 문자열, 쉬운 질문
writeStr []=putChar ' '
writeStr (x:xs) = (putChar x)(writeStr xs)
안녕하세요, 미리 감사드립니다, 형식 오류가 발생합니다, 그것은 간단한 대답이되어야하지만 나는 어디에서 오류가 오는지 얻지 못합니다.하스켈 작성 문자열, 쉬운 질문
코드가 약간 이상합니다. 내가 맞으면 문자열을 인쇄하려고합니다. 당신의 방법은 첫 번째 문자열을 넣고 두 번째 문자열을 넣는 것입니다. 하지만 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
...
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
당신이 있습니까 쓸 수 있습니다 'putStr'과'putStrLn'을 사용하지 않는 이유는 무엇입니까? 어떤 경우에도 문자열은 문자 목록 일 뿐이므로 writeStr은 단순히 'writeStr = mapM_ putChar'로 정의 할 수 있습니다. –