Haskell
モナド
供養
わーい、すごーい

わーい、すごーい、モナドがたくさんあるねー!

More than 1 year has passed since last update.

元ネタ
わーい、すごーい

タイトルの元ネタ
4話のサーバルちゃんの「砂がたくさんあるねー!」
『けものフレンズ』4話、サーバルちゃんのあるセリフがすごく深い「見落としてるものを気づかせてくれる」

Stateモナド

戻り値と一緒に返した状態を引き回せるモナドなんだね!すごーい!

import Control.Monad.State (State, modify, execState)

type Friends = State String ()

wai :: Friends
wai = modify (++ "わーい!\n")

sugoi :: Friends
sugoi = modify (++ "すごーい!\n")

tanoshii :: Friends
tanoshii = modify (++ "たーのしー!\n")

friends :: String -> Friends
friends skill = modify (++ "君は" ++ skill ++ "が得意なフレンズなんだね!\n")

main :: IO ()
main = putStrLn $ flip execState "" $ do
  wai
  sugoi
  tanoshii
  friends "クソコード"

Writerモナド

ログをどんどん追記できるモナドなんだね!すごーい!

import Control.Monad.Writer (Writer, tell, execWriter)

type Friends = Writer String ()

wai :: Friends
wai = tell "わーい!\n"

sugoi :: Friends
sugoi = tell "すごーい!\n"

tanoshii :: Friends
tanoshii = tell "たーのしー!\n"

friends :: String -> Friends
friends skill = tell $ "君は" ++ skill ++ "が得意なフレンズなんだね!\n"

main :: IO ()
main = putStrLn $ execWriter $ do
  wai
  sugoi
  tanoshii
  friends "クソコード"

Readerモナド

読み取り専用の値を共有できるモナドなんだね!すごーい!

import Control.Monad.Reader (Reader, ask, local, runReader)

type Friends = Reader String String

wai :: Friends
wai = do
  message <- ask
  return $ message ++ "わーい!\n"

sugoi :: Friends
sugoi = do
  message <- ask
  return $ message ++ "すごーい!\n"

tanoshii :: Friends
tanoshii = do
  message <- ask
  return $ message ++ "たーのしー!\n"

friends :: String -> Friends
friends skill = do
  message <- ask
  return $ message ++ "君は" ++ skill ++ "が得意なフレンズなんだね!\n"

main :: IO ()
main = putStrLn $ flip runReader "" $ do
  message1 <- wai
  message2 <- local (const message1) sugoi
  message3 <- local (const message2) tanoshii
  local (const message3) (friends "クソコード")

STモナド

破壊的代入ができるモナドなんだね!すごーい!

import Control.Monad.ST (ST, runST)
import Data.STRef (STRef, newSTRef, modifySTRef, readSTRef)

type Friends s = STRef s String -> ST s ()

wai :: Friends s
wai = flip modifySTRef (++ "わーい!\n")

sugoi :: Friends s
sugoi = flip modifySTRef (++ "すごーい!\n")

tanoshii :: Friends s
tanoshii = flip modifySTRef (++ "たーのしー!\n")

friends :: String -> Friends s
friends skill = flip modifySTRef (++ "君は" ++ skill ++ "が得意なフレンズなんだね!\n")

main :: IO ()
main =  putStrLn $ runST $ do
  message <- newSTRef ""
  wai message
  sugoi message
  tanoshii message
  friends "クソコード" message
  readSTRef message