모나드란 무엇일까요? (하스켈, 함수형 프로그래밍)

2024-07-27

모나드의 이해를 돕는 몇 가지 주요 개념:

  • 값 포장: 모나드는 값을 포장하여 새로운 값을 생성합니다. 이 새로운 값은 원래 값뿐만 아니라 추가적인 정보나 기능을 포함할 수 있습니다. 예를 들어, Maybe 모나드는 값이 있을 수도 있고 없을 수도 있는 경우를 다루기 위한 모나드입니다. Maybe 모나드는 값이 있는 경우 Some(값) 형태로, 값이 없는 경우 Nothing 형태로 값을 포장합니다.
  • 바인드 연산: 바인드 연산은 모나드 내부의 값을 꺼내 함수를 적용하고, 다시 모나드 컨테이너에 담아 새로운 모나드 값을 생성하는 연산입니다. 바인드 연산은 모나드 연산들을 순차적으로 연결하는 데 사용됩니다.
  • 순수성: 모나드는 순수 함수 프로그래밍 스타일을 지원합니다. 모나드 연산은 입력 값에만 의존하고 외부 상태에 영향을 미치지 않습니다.

모나드의 활용:

  • 에러 처리: Maybe 모나드는 값이 없을 수 있는 경우를 처리하는 데 사용됩니다. 예를 들어, 파일을 읽는 함수는 파일이 존재하지 않을 수 있으므로 Maybe 모나드를 사용하여 결과를 반환할 수 있습니다.
  • 비동기 처리: IO 모나드는 비동기 작업을 처리하는 데 사용됩니다. 예를 들어, 파일을 쓰는 함수는 IO 모나드를 사용하여 작업을 시작하고 나중에 결과를 반환할 수 있습니다.
  • 상태 관리: State 모나드는 프로그램 상태를 관리하는 데 사용됩니다. State 모나드를 사용하면 프로그램 상태를 명시적으로 전달하고 변경할 수 있습니다.



모나드 예제 코드 (하스켈)

-- Maybe 모나드를 정의합니다.
data Maybe a = Nothing | Just a

-- 문자열을 숫자로 변환하는 함수 (문자열이 숫자가 아닌 경우 Nothing 반환)
strToInt :: String -> Maybe Int
strToInt s = if all (\c -> isDigit c) s then Just (read s :: Int) else Nothing

-- Maybe 값을 제곱하는 함수
squareMaybe :: Maybe Int -> Maybe Int
squareMaybe (Just n) = Just (n * n)
squareMaybe Nothing = Nothing

-- 두 숫자를 더하는 함수
add :: Int -> Int -> Int
add x y = x + y

-- Maybe 모나드를 사용하여 두 문자열을 숫자로 변환하고 더한 후 제곱합니다.
result = squareMaybe (addMaybe (strToInt "10") (strToInt "20"))

-- 결과 출력
putStrLn (show result)

설명:

  • strToInt 함수는 문자열을 숫자로 변환하는 함수입니다. 문자열이 숫자가 아닌 경우 Nothing을 반환합니다.
  • squareMaybe 함수는 Maybe 값을 제곱하는 함수입니다. Just 값이 있는 경우 값을 제곱하고, Nothing 값인 경우 Nothing을 반환합니다.
  • add 함수는 두 숫자를 더하는 함수입니다.
  • result 변수는 Maybe 모나드를 사용하여 두 문자열을 숫자로 변환하고 더한 후 제곱합니다. strToInt 함수는 Maybe 값을 반환하므로, addMaybe 함수를 사용하여 두 Maybe 값을 더합니다. 마지막으로 squareMaybe 함수를 사용하여 결과를 제곱합니다.
  • putStrLn 함수는 result 변수의 값을 출력합니다.

IO 모나드를 사용한 파일 입출력:

-- IO 모나드를 정의합니다.
type IO a = (() -> a)

-- 파일을 읽는 함수
readFile :: String -> IO String
readFile fileName = readFileContents fileName

-- 문자열을 파일에 쓰는 함수
writeFile :: String -> String -> IO ()
writeFile fileName content = writeFileContents fileName content

-- 두 파일의 내용을 연결하여 새 파일에 쓰는 함수
combineFiles :: String -> String -> String -> IO ()
combineFiles input1 input2 output = do
  contents1 <- readFile input1
  contents2 <- readFile input2
  let combinedContent = contents1 ++ "\n" ++ contents2
  writeFile output combinedContent

-- 예제 실행
combineFiles "input1.txt" "input2.txt" "output.txt"
  • readFile 함수는 파일의 내용을 문자열로 읽는 함수입니다.
  • writeFile 함수는 문자열을 파일에 씁니다.
  • combineFiles 함수는 두 파일의 내용을 연결하여 새 파일에 씁니다.
  • do 키워드는 IO 모나드 연산을 순차적으로 실행하는 데 사용됩니다.
  • 마지막 줄은 combineFiles 함수를 실행하여 "input1.txt"와 "input2.txt"의 내용을 연결하여 "output.txt" 파일에 씁니다.

State 모나드를 사용한 계산기:

-- State 모나드를 정의합니다.
type State a s = (s -> (a, s))

-- 초기 상태
initialState = 0

-- 더하기 연산
add :: Int -> State Int Int
add n (state, _) = (n + state, state)

-- 곱하기 연산
multiply :: Int -> State Int Int
multiply n (state, _) = (n * state, state)

-- 두 숫자를 더하고 곱하는 함수
calculate :: Int -> Int -> State Int Int
calculate x y = do
  (sum, newState1) <- add x (initialState, _)
  (result, newState2) <- multiply y (newState1, _)
  return (result, newState2)

-- 예제 실행
(result, _) = calculate 10 20

-- 결과 출력
putStrLn (show result)
  • State 모나드는 계산기를 나타냅니다. State 값은 두 가지 구성 요



  • 코드에서 오류가 발생했을 때 대체 방법:
    • 디버깅 도구를 사용하여 오류의 근본 원인을 파악하고 해결합니다.
    • 오류를 우회하거나 무시하는 코드를 작성합니다. (단, 근본적인 해결책이 아님)
    • 다른 라이브러리나 모듈을 사용합니다.
  • 요리 재료가 없을 때 대체 재료:
    • 비슷한 맛이나 기능을 가진 다른 재료를 사용합니다.
    • 레시피를 조정합니다.
    • 생략합니다.

haskell functional-programming monads

haskell functional programming monads

꼬리 재귀란 무엇일까요? (알고리즘, 언어 비의존적, 함수형 프로그래밍)

꼬리 재귀의 특징:함수의 마지막 작업이 재귀 호출인 경우재귀 호출 후 더 이상의 계산이나 작업이 없는 경우꼬리 재귀의 장점:메모리 사용량 감소: 스택 프레임 재사용으로 메모리 할당 감소성능 향상: 메모리 부담 감소로 인한 처리 속도 향상