SlideShare a Scribd company logo
MP in Haskell
MP = Monadic Programming
1. モナドとは何か
2. モナドの基本的な扱い方
3. モナド変換子の使い方
自己紹介
(defprofile
大橋 賢人 [OHASHI Kent]
:company 株式会社オプト テクノロジー開発2部
:github @lagenorhynque
:twitter @lagenorhynque
:languages [Python Haskell Clojure Scala English français Deutsch русский]
:interests [プログラミング 語学 数学])
モナド(Monad)とは
一言で言えば、 >>=(bind) できる型クラス(type class)。
m a -> (a -> m b) -> m b
型クラスFunctor, Applicativeの上位互換。
-- Haskell
class Applicative m => Monad m where
(>>=) :: forall a b. m a -> (a -> m b) -> m b
return :: a -> m a
...
// scalaz.Monad
trait Monad[F[_]] extends Applicative[F] with Bind[F] {
abstract def bind[A, B](fa: F[A])(f: (A) ⇒ F[B]): F[B]
abstract def point[A](a: ⇒ A): F[A]
...
}
モナドの具体例
例えば、 。Maybe
型クラスFunctor, Applicative, Monadのインスタンスになっている。
Functorの fmap / <$>
(a -> b) -> f a -> f b
n :: Maybe Int
n = Just 1
f :: Int -> String
f = x -> show x
-- fmap
fmap f n
-- <$>
f <$> n
-- >>= による実装
n >>= return . f
-- do記法による実装
do
a <- n
return $ f a
Applicativeの <*>
f (a -> b) -> f a -> f b
n :: Maybe Int
n = Just 1
f :: Maybe (Int -> String)
f = Just $ x -> show x
-- <*>
f <*> n
-- >>= による実装
n >>= a ->
f >>= g ->
return $ g a
-- do記法による実装
do
a <- n
g <- f
return $ g a
Monadの >>=
m a -> (a -> m b) -> m b
n :: Maybe Int
n = Just 1
f :: Int -> Maybe String
f = x -> Just $ show x
-- >>=
n >>= f
-- do記法による実装
do
a <- n
f a
同種のモナドを扱う場合
例えば、 Maybeを単独で使う場合
同種のモナドを扱う場合
(1) パターンマッチ
構造に注目して分解(unapply, destructure)する。
data User = User {
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userName :: User -> Maybe String
userName User {firstName = Just f, lastname = Just l} = Just $ f ++ " " ++ l
userName _ = Nothing
同種のモナドを扱う場合
(2) 高階関数
高階関数>>=, etc.を組み合わせる。
data User = User {
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userName :: User -> Maybe String
userName user =
firstName user >>= f ->
lastName user >>= l ->
return $ f ++ " " ++ l
同種のモナドを扱う場合
(3) do記法
モナドのためのシンタックスシュガーを活用する。
data User = User {
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userName :: User -> Maybe String
userName user = do
f <- firstName user
l <- lastName user
return $ f ++ " " ++ l
異種のモナドが混在する場合
例えば、 Maybeと を組み合わせてEither
Either e (Maybe a)として扱う必要がある場合
異種のモナドが混在する場合
(1) パターンマッチ
data User = User {
id' :: Int,
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userRole :: Int -> Either Error Role
userRole i = undefined
userInfo :: User -> Either Error (Maybe String)
userInfo user = case userRole $ id' user of
Right r -> case user of
User {firstName = Just f, lastName = Just l} ->
Right . Just $ f ++ " " ++ l ++ ": " ++ show r
_ ->
Right Nothing
Left e -> Left e
問題点
複数階層のモナドの分解・再構築が煩わしい
構造に強く依存しているため変更に弱い
パターンマッチがネストして書きづらく読みづらい
異種のモナドが混在する場合
(2) 高階関数
data User = User {
id' :: Int,
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userRole :: Int -> Either Error Role
userRole i = undefined
userInfo :: User -> Either Error (Maybe String)
userInfo user =
userRole (id' user) >>= r ->
return $ firstName user >>= f ->
lastName user >>= l ->
return $ f ++ " " ++ l ++ ": " ++ show r
問題点
構造を直接扱う必要はないが関数がネストして書きづらく読みづらい
異種のモナドが混在する場合
(3) do記法
data User = User {
id' :: Int,
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userRole :: Int -> Either Error Role
userRole i = undefined
userInfo :: User -> Either Error (Maybe String)
userInfo user = do
r <- userRole $ id' user
return $ do
f <- firstName user
l <- lastName user
return $ f ++ " " ++ l ++ ": " ++ show r
問題点
関数はネストしないがdo記法が連鎖して書きづらく読みづらい
モナド変換子(monad transformer)とは
一言で言えば、あるモナドに別のモナドを上乗せ(合成)したモナド。
ネストしたモナドをネストしていないかのように扱えるようになる。
e.g. , ,MaybeTEitherTListT
モナド変換子の生成と変換
-- M(モナド)とMaybeでネストしたモナド
mMaybeA :: M (Maybe a)
-- MaybeとMを合成したMaybeT
maybeTMA :: MaybeT M a
-- Maybe
maybeA :: Maybe a
-- M
mA :: M a
-- M (Maybe a) → MaybeT M a
MaybeT mMaybeA
-- MaybeT M a → M (Maybe a)
runMaybeT maybeTMA
-- Maybe a → M (Maybe a) → MaybeT M a
MaybeT $ return maybeA
-- M a → MaybeT M a
lift mA
モナド変換子の導入
ここではモナド変換子MaybeTを利用して
MaybeとEitherを合成してみる。
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
data User = User {
id' :: Int,
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userRole :: Int -> Either Error Role
userRole i = undefined
userInfo :: User -> Either Error (Maybe String)
userInfo user = runMaybeT $ do
r <- lift . userRole $ id' user
f <- MaybeT . return $ firstName user
l <- MaybeT . return $ lastName user
return $ f ++ " " ++ l ++ ": " ++ show r
Maybe aとEither e aをdo記法1つでシンプルに扱える
モナド変換子への変換がやや冗長
さらにリファクタ
モナド変換子への変換を関数として抽出してみる。
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
data User = User {
id' :: Int,
firstName :: Maybe String,
lastName :: Maybe String
} deriving Show
userRole :: Int -> Either Error Role
userRole i = undefined
fromMaybe :: Maybe a -> MaybeT (Either Error) a
fromMaybe = MaybeT . return
userInfo :: User -> Either Error (Maybe String)
userInfo user = runMaybeT $ do
r <- lift . userRole $ id' user
f <- fromMaybe $ firstName user
l <- fromMaybe $ lastName user
return $ f ++ " " ++ l ++ ": " ++ show r
Further Reading
Functor, Applicative, Monadのシンプルな定式化- Qiita
ScalaでFutureとEitherを組み合わせたときに綺麗に書く方法- scala
とか・・・
Scalaz Monad Transformers - Underscore
独習Scalaz — モナド変換子
Easy Monad
Haskell モナド変換子超入門- Qiita
All About Monads - Sampou.Org
Source Code
Gist - lagenorhynque - monad-transformers

More Related Content

PDF
MP in Scala
PPTX
大人のお型付け
PDF
Ekmett勉強会発表資料
PDF
すごいHaskell楽しく学ぼう-第12章モノイド-
PDF
たのしい高階関数
PDF
F#入門 ~関数プログラミングとは何か~
ODP
Ekmett勉強会発表資料
PDF
これからの「言語」の話をしよう ―― 未来を生きるためのツール
MP in Scala
大人のお型付け
Ekmett勉強会発表資料
すごいHaskell楽しく学ぼう-第12章モノイド-
たのしい高階関数
F#入門 ~関数プログラミングとは何か~
Ekmett勉強会発表資料
これからの「言語」の話をしよう ―― 未来を生きるためのツール

What's hot (20)

PDF
関数プログラミング入門
PDF
関数型プログラミング入門 with OCaml
PDF
C++コミュニティーの中心でC++をDISる
PDF
Van laarhoven lens
PDF
Implicit Explicit Scala
ODP
Real World OCamlを読んでLispと協調してみた
PDF
20141128 iOSチーム勉強会 My Sweet Swift
PPTX
ナウなヤングにバカうけのイカしたタグ付き共用体
PDF
Implicit Implicit Scala
PDF
Freer Monads, More Extensible Effects
PDF
今から始める Lens/Prism
PDF
やさしく知りたいC言語
PDF
Haskell Lecture 2
PPT
Pythonintro
PDF
たのしい関数型
PDF
Swift らしい表現を目指そう #eventdots
ODP
(define)なしで再帰関数を定義する
PDF
並行プログラミングと継続モナド
PDF
Material
PDF
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
関数プログラミング入門
関数型プログラミング入門 with OCaml
C++コミュニティーの中心でC++をDISる
Van laarhoven lens
Implicit Explicit Scala
Real World OCamlを読んでLispと協調してみた
20141128 iOSチーム勉強会 My Sweet Swift
ナウなヤングにバカうけのイカしたタグ付き共用体
Implicit Implicit Scala
Freer Monads, More Extensible Effects
今から始める Lens/Prism
やさしく知りたいC言語
Haskell Lecture 2
Pythonintro
たのしい関数型
Swift らしい表現を目指そう #eventdots
(define)なしで再帰関数を定義する
並行プログラミングと継続モナド
Material
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Ad

Viewers also liked (18)

PDF
おいしいLisp
PDF
Functional Way
PDF
From Java To Clojure (English version)
PPTX
Clojure座談会 #1 LT 独自コレクションを定義しよう
DOCX
Rデモ01_はじめの一歩2016
PPTX
Rプログラミング01 はじめの一歩
PDF
ロジカル・シンキング & システム設計・プログラミングについて
DOCX
Rデモ02_入出力編2016
DOCX
Rデモ03_データ分析編2016
PPTX
Rプログラミング02 データ入出力編
PDF
HTTP/2 in nginx(2016/3/11 社内勉強会)
ODP
Haskellの型安全性の力よ〜参照透明性編〜
PPTX
Rプログラミング03 データ分析編
PPTX
TypeScriptハンズオン第1回テキスト
PDF
ネットワーク概論 サーバの構築理論
PDF
Haskell勉強会 14.1〜14.3 の説明資料
PDF
From Java To Clojure
PDF
Practical Phonetics (実践音声学)
おいしいLisp
Functional Way
From Java To Clojure (English version)
Clojure座談会 #1 LT 独自コレクションを定義しよう
Rデモ01_はじめの一歩2016
Rプログラミング01 はじめの一歩
ロジカル・シンキング & システム設計・プログラミングについて
Rデモ02_入出力編2016
Rデモ03_データ分析編2016
Rプログラミング02 データ入出力編
HTTP/2 in nginx(2016/3/11 社内勉強会)
Haskellの型安全性の力よ〜参照透明性編〜
Rプログラミング03 データ分析編
TypeScriptハンズオン第1回テキスト
ネットワーク概論 サーバの構築理論
Haskell勉強会 14.1〜14.3 の説明資料
From Java To Clojure
Practical Phonetics (実践音声学)
Ad

Similar to MP in Haskell (6)

KEY
モナドがいっぱい!
PDF
モナドハンズオン前座
PDF
リストモナドを作ってみた
PDF
Essential Scala 第5章 シーケンス処理
PDF
すごいH 第12章モノイド
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
モナドがいっぱい!
モナドハンズオン前座
リストモナドを作ってみた
Essential Scala 第5章 シーケンス処理
すごいH 第12章モノイド
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜

More from Kent Ohashi (20)

PDF
関数型言語テイスティング: Haskell, Scala, Clojure, Elixirを比べて味わう関数型プログラミングの旨さ
PDF
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
PDF
From Scala/Clojure to Kotlin
PDF
TDD with RDD: Clojure/LispのREPLで変わる開発体験
PDF
🐬の推し本紹介2024: 『脱・日本語なまり 英語(+α)実践音声学』
PDF
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
PDF
map関数の内部実装から探るJVM言語のコレクション: Scala, Kotlin, Clojureコレクションの基本的な設計を理解しよう
PDF
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
PDF
RDBでのツリー表現入門2024
PDF
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
PDF
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
PDF
Team Geek Revisited
PDF
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
PDF
Clojureコレクションで探るimmutableでpersistentな世界
PDF
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
PDF
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
PDF
実用のための語源学入門
PDF
メタプログラミング入門
PDF
労働法の世界
PDF
Clojureで作る"simple"なDSL
関数型言語テイスティング: Haskell, Scala, Clojure, Elixirを比べて味わう関数型プログラミングの旨さ
純LISPから考える関数型言語のプリミティブ: Clojure, Elixir, Haskell, Scala
From Scala/Clojure to Kotlin
TDD with RDD: Clojure/LispのREPLで変わる開発体験
🐬の推し本紹介2024: 『脱・日本語なまり 英語(+α)実践音声学』
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
map関数の内部実装から探るJVM言語のコレクション: Scala, Kotlin, Clojureコレクションの基本的な設計を理解しよう
Kotlin Meets Data-Oriented Programming: Kotlinで実践する「データ指向プログラミング」
RDBでのツリー表現入門2024
ミュータビリティとイミュータビリティの狭間: 関数型言語使いから見たKotlinコレクション
インターフェース定義言語から学ぶモダンなWeb API方式: REST, GraphQL, gRPC
Team Geek Revisited
Scala vs Clojure?: The Rise and Fall of Functional Languages in Opt Technologies
Clojureコレクションで探るimmutableでpersistentな世界
英語学習者のためのフランス語文法入門: フランス語完全理解(?)
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
実用のための語源学入門
メタプログラミング入門
労働法の世界
Clojureで作る"simple"なDSL

MP in Haskell