Upgrade to Pro — share decks privately, control downloads, hide ads and more …

IO (Maybe a)

IO (Maybe a)

Tomohiko Himura

July 03, 2016
Tweet

More Decks by Tomohiko Himura

Other Decks in Programming

Transcript

  1. ghci> :kind IO IO :: * -> * ghci> :kind

    Maybe Maybe :: * -> * ghci> :kind String String :: * ghci> :kind Maybe String Maybe String :: * IOやMaybeは * をうけとって *を返す。 * であるStringを渡すと * になる。 Maybe Stringは * なので IOに渡せる。 Maybe は * -> * なので IOに渡せない。
  2. 環境変数を取得する ghci> :type System.Environment.lookupEnv System.Environment.lookupEnv :: String -> IO (Maybe

    String) 変数名があれば値がとれる。 値は実行するタイミングによっては変わる 値はないこともある。
  3. $ stack ghci ghci> :type System.Environment.lookupEnv "Hoge" System.Environment.lookupEnv "Hoge" ::

    IO (Maybe String) ghci> System.Environment.lookupEnv "Hoge" Nothing Hogeは未定義なので値はとれない
  4. 愚直にdoを使ってみる import System.Environment import Data.Maybe sample = do -- IOͷͨΊͷdo

    maybeHoge <- lookup "Hoge" -- maybeHoge ͸ IO͕ͱΕͯ Maybe Stringɹͱ͍͏ܕ ʹͳ͍ͬͯΔ return $ do -- Maybe ͷͨΊͷdo IOͷdoͷதʹ͔͚ΔΑ͏ʹ return Λ͚ͭΔ ɹɹ hoge <- maybeHoge -- hoge͸Maybe͕͸ͣΕͯ String ɹɹ return . putStrLn $ hoge -- hogeͷ಺༰Λग़ྗɻίϯύΠϧ͕௨ΔΑ͏ʹ returnΛ ͚ͭͯ͋͛Δ sampleの型は IO (Maybe (IO ())) Hogeが定義されていたら、標準出力に内容を出力。未定義 だったときのことが考慮されていないため、3重になって いる doが二重になってあたりもつらい。
  5. さっき作ったsampleを使う $ stack ghci ghci> sample >>= fromMaybe (putStrLn "not

    found Hoge") not found Hoge 未定義の時の処理を追加して使う。 Hogeが未定義なのでfromMaybeで追加し た処理が動いている $ Hoge=aaa stack ghci ghci> sample >>= fromMaybe (putStrLn "not found Hoge") aaa こっちはHogeがあるのでHogeの内容 が表示されている
  6. 値がない場合はnot foundに 型は IO () sample2 = do maybeHoge <-

    lookupEnv "Hoge" let hoge = fromMaybe "not found" maybeHoge -- ͜ͷ࣌఺ͰMaybeΛ֎͓ͯ͘͠ɻ NothingͳΒ "not found"ʹͳΔ putStrLn hoge $ stack ghci ghci> sample2 not found $ Hoge="aaa" stack ghci ghci> sample2 aaa 使うのも簡単
  7. * -> * を受け取れる ghci> :kind MaybeT MaybeT :: (*

    -> *) -> * -> * ghci> :kind MaybeT IO MaybeT IO :: * -> * ghci> :kind IO IO :: * -> * ghci> :kind Maybe Maybe :: * -> *
  8. sample3の型は MaybeT IO String import System.Environment import Data.Maybe import Control.Monad.Trans.Maybe

    sample3 = do hoge <- MaybeT $ lookupEnv "Hoge" -- IO (Maybe String)Λ MaybeT IO Stringʹม׵ͨ͠ɻശ͸ҰͭͳͷͰ <- Ͱ஋Λͻͬͺͯ͘Δͱ Stringʹͳ͍ͬͯΔ lift $ putStrLn hoge -- IO () ͳͷͰ MaybeT IO () ʹม׵
  9. sample3を使ってみる $ stack ghci ghci> runMaybeT sample3 -- IO (Maybe

    String)ʹͳΔͷͰ࣮ߦͰ͖ͯɺ Maybe Stringʹ ͳΔ Nothing ghci> runMaybeT sample3 >>= maybe (putStrLn "not found") (const return ()) -- ޙ͔Βॲཧͷ௥Ճ΋Ͱ͖Δ "notFound" $ Hoge=aaa stack ghci ghci> runMaybeT sample3 aaa ghci> runMaybeT sample3 >>= maybe (putStrLn "not found") (const return ()) aaa ghciはIO aな型は実行してaにしてくれる機能があるっぽい。
 MaybeTをつかうと1重のモナドとして扱えて便利。 元に戻すこともできる
  10. sample3と同じ動きをするように書いてみる sample1_5 = do maybeHoge <- lookupEnv "Hoge" case maybeHoge

    of Just hoge -> putStrLn hoge >> return (Just ()) Nothing -> return Nothing 一度Maybeを自分で解いて、再度同じようになるように値を構 築している。最初の例はMaybeを解かずにdoをつかったため、 IO (Maybe (IO ())) となってしまった。
  11. 4USJOH .BZCF 4USJOH .BZCF 4USJOH *0 .BZCF5*0 4USJOH *0 4USJOH

    return return return return runMaybeT MaybeT lift