모나드(Monad)는 순차적 계산의 패턴을 추상화한 함수형 프로그래밍의 핵심 개념이다. 부수 효과(IO, 상태, 예외, 비결정성)를 순수 함수형 스타일로 다룰 수 있게 한다.
모나드 정의
haskell
class Functor m => Monad m where
return :: a -> m a -- 순수값을 모나드로 감쌈
(>>=) :: m a -> (a -> m b) -> m b -- bind (순차 합성)
-- 모나드 법칙:
-- 왼쪽 항등: return a >>= f ≡ f a
-- 오른쪽 항등: m >>= return ≡ m
-- 결합법칙: (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
Maybe 모나드
haskell
-- 실패 가능한 계산 체이닝
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv a b = Just (a `div` b)
safeLog :: Int -> Maybe Double
safeLog n
| n <= 0 = Nothing
| otherwise = Just (log (fromIntegral n))
-- do 표기법으로 체이닝
compute :: Int -> Int -> Maybe Double
compute a b = do
x <- safeDiv a b -- Nothing이면 전체 Nothing
y <- safeLog x
return y
-- 명시적 bind
compute a b =
safeDiv a b >>= \x ->
safeLog x >>= \y ->
return y
IO 모나드
haskell
main :: IO ()
main = do
putStrLn "이름을 입력하세요:"
name <- getLine
putStrLn ("안녕하세요, " ++ name ++ "!")
-- IO는 실제로 부수 효과가 아닌
-- "실행할 액션의 설명"을 값으로 다룸
State 모나드
haskell
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = do
(x:xs) <- get
put xs
return x
push :: Int -> State Stack ()
push x = modify (x:)
stackOps :: State Stack Int
stackOps = do
push 3
push 5
a <- pop
b <- pop
return (a + b)
runState stackOps [] -- (8, [])
주요 모나드 비교
| 모나드 | 효과 | 용도 |
|---|
| Maybe | 실패 가능성 | 안전한 계산 |
| Either e | 에러 정보 | 예외 처리 |
| IO | 부수 효과 | 입출력 |
| State s | 가변 상태 | 상태 관리 |
| Reader r | 읽기 환경 | 의존성 주입 |
| Writer w | 로그 축적 | 로깅 |
| List | 비결정성 | 탐색/생성 |
관련 개념