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

IO (Maybe a)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

IO (Maybe a)

Avatar for Tomohiko Himura

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