본문 바로가기

Haskell

헬로월드 X N

이번 문제는 hello world를 N번 찍는 문제이다. "간단한" 반복문 문제인데, 함수형 언어에서 반복문이라는게 있던가?

재귀적인 접근

함수형 언어에서는 반복문 대신에 함수의 재귀호출로 이를 대신한다. 따라서 다음과 같이 재귀호출을 이용한 함수를 생각해볼 수 있다. 이러한 패턴은 함수형 언어에서 반복문을 대체하는 가장 기본적인 패턴이다.


sayHello :: Int -> IO ()
sayHello 0 = return ()
sayHello n = do
  putStrLn "Hello World"
  sayHello (n-1)

아래와 같이 확인해볼 수 있다.


main :: IO ()
main = do
  n <- read <$> getLine
  sayHello n

좀 더 간단한 방법

조금 더 간단한 방법에 대해서 연구해보자. 먼저 이를 반복문이 아닌 "Hello World"의 n개 짜리 리스트로 생각하는 것이다. 이를 unlines로 하나의 멀티라인 문자열로 합친다음에 출력하면 된다.


sayHello2 n = putStrLn hellos
    where hellos = ["Hello World" | _ <- [1..n]

이는 결국 동일한 원소를 반복해서 리스트를 만드는 것이므로 replicate를 사용하면 된다. 즉 1) "Hello World"를 n 개 반복해서 리스트를 만들고 2)이를 unlines를 이용해서 하나로 합친다음, 3) 출력한다.


sayHello3 n = putStrLn . unlines . replicate n $ "Hello World"

모나드에서의 다른 방법 : replicateM_

replicateM의 시그니처는 Applicative m => Int -> m a -> m [a]이다. Applicative 속성의 타입 a를 N번 반복해서 리스트로 만들어준다는 것인데, 우리가 만든 sayHello*들은 모두 Int -> IO () 타입으로 반복해서 만든 리스트는 별로 필요가 없다. 이럴 때는 언더스코어가 뒤에 붙은 replicateM_을 고려해볼 수 있다.


import Control.Monad
sayHello4 n = replicateM_ n $ putStrLn "Hello World"